Přeskočit na hlavní obsah

Kvantová teleportace a superhusté kódování

poznámka

Kifumi Numata (26 Apr 2024)

Stáhnout PDF originální přednášky. Vezměte prosím na vědomí, že některé úryvky kódu mohou být zastaralé, protože se jedná o statické obrázky.

Approximate QPU time to run this experiment is 10 seconds.

1. Úvod

Abychom mohli řešit jakýkoli kvantový problém v užitkovém měřítku, budeme potřebovat přesouvat informace na kvantovém počítači z jednoho Qubitu na druhý. Pro tento účel existují dobře známé protokoly, přičemž některé z nejzákladnějších byly formulovány v kontextu odesílání informací mezi vzdálenými stranami. V průběhu této lekce budeme někdy používat jazyk odpovídající tomuto kontextu, například „vzdálení přátelé posílající informace". Mějte však na paměti, že tyto protokoly mají v kvantovém výpočetnictví širší význam. V této lekci se budeme zabývat následujícími protokoly kvantové komunikace:

  • Kvantová teleportace Využití sdíleného provázaného stavu (někdy nazývaného e-bit) k odeslání neznámého kvantového stavu vzdálenému příteli, přičemž je vyžadována doplňková klasická komunikace.
  • Kvantové superhusté kódování Jak odeslat dva bity informace zasláním jediného Qubitu vzdálenému příteli (opět s využitím předem sdílených provázaných Qubitů).

Pro více kontextu k těmto tématům doporučujeme lekci 4 v kurzu Základy kvantových informací na stránce Provázanost v praxi.

Ve výše uvedeném popisu „neznámý kvantový stav" jednoduše označuje stav ve tvaru popsaném v předchozí lekci:

ψ=α0+β1|\psi\rangle =\alpha|0\rangle+\beta|1\rangle

kde α\alpha a β\beta jsou komplexní čísla taková, že α2+β2=1|\alpha|^2+|\beta|^2 = 1. To nám umožňuje zapsat kvantový stav jako

ψ=cosθ20+eiφsinθ21=(cosθ2eiφsinθ2)|\psi\rangle =\cos\frac{\theta}{2}|0\rangle+e^{i\varphi}\sin\frac{\theta}{2}|1\rangle= \left( \begin{matrix} \cos\frac{\theta}{2}\\ e^{i\varphi}\sin\frac{\theta}{2} \end{matrix} \right)

Protože chceme být schopni přenášet informace v libovolném náhodném kvantovém stavu, začneme tuto lekci právě generováním takového stavu.

2. Matice hustoty

Kvantový stav ψ|\psi \rangle lze zapsat také ve formě matice hustoty. Tato forma je užitečná pro vyjádření pravděpodobnostní směsi čistých kvantových stavů. V případě jednoho Qubitu lze psát

ψψρ=((cosθ2eiφsinθ2))((cosθ2eiφsinθ2))=12((1+cosθeiφsinθeiφsinθ1cosθ))|\psi \rangle \langle \psi| \equiv \rho = \left( \begin{pmatrix} \cos\frac{\theta}{2}\\ e^{i\varphi}\sin\frac{\theta}{2} \end{pmatrix} \right) \left( \begin{pmatrix} \cos\frac{\theta}{2} & e^{-i\varphi}\sin\frac{\theta}{2} \end{pmatrix} \right) =\frac{1}{2}\left(\begin{pmatrix} 1+\cos\theta & e^{-i\varphi}\sin\theta\\ e^{-i\varphi}\sin\theta & 1-\cos\theta \end{pmatrix}\right)

Všimni si, že matice hustoty ρ\rho je lineární kombinací Pauliho matic, jak je uvedeno níže:

ρ=12(I+(sinθcosφ)X+(sinθsinφ)Y+(cosθ)Z)\rho = \frac{1}{2}\bigl( \textbf{I} + (\sin{\theta}\cos{\varphi})\textbf{X}+ (\sin{\theta}\sin{\varphi})\textbf{Y} + (\cos{\theta})\textbf{Z} \bigr)

Nebo obecně:

ρ=12(I+rxX+ryY+rzZ)\rho = \frac{1}{2}(\textbf{I} + r_{x}\textbf{X}+ r_{y}\textbf{Y} + r_{z}\textbf{Z})

kde rx2+ry2+rz2=1r_{x}^2+r_{y}^2+r_{z}^2=1.

Blochův vektor je r=(rx,ry,rz)\textbf{r} = (r_{x}, r_{y}, r_{z}).

Nyní vytvoříme libovolný kvantový stav pomocí náhodných čísel.

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
import numpy as np

# create a random 1-qubit state from a random (theta, varphi) to define r vector
np.random.seed(1) # fixing seed for repeatibility

theta = np.random.uniform(0.0, 1.0) * np.pi # from 0 to pi
varphi = np.random.uniform(0.0, 2.0) * np.pi # from 0 to 2*pi

def get_r_vec(theta, varphi):
rx = np.sin(theta) * np.cos(varphi)
ry = np.sin(theta) * np.sin(varphi)
rz = np.cos(theta)
return (rx, ry, rz)

# get r vector
rx, ry, rz = get_r_vec(theta, varphi)

print("theta=" + str(theta), ",varphi=" + str(varphi))
print("(rx, ry, rz) = (" + str(rx) + ", " + str(ry) + ", " + str(rz) + ")")
theta=1.3101132663588946 ,varphi=4.525932273597346
(rx, ry, rz) = (-0.1791150283307452, -0.9494670044331133, 0.2577405946274022)

Tento Blochův vektor lze zobrazit na Blochově sféře.

from qiskit.visualization import plot_bloch_vector

r = [rx, ry, rz]
plot_bloch_vector(r)

Output of the previous code cell

3. Kvantová stavová tomografie

Pokud měříš kvantový stav pouze ve výpočetní bázi (0|0 \rangle a 1|1 \rangle), informace o fázi (informace o komplexních číslech) se ztratí. Ale pokud máme mnoho kopií ψ|\psi \rangle opakováním přípravného procesu (stavy nelze klonovat, ale přípravné procesy lze opakovat), můžeme odhadnout hodnoty rx,ry,rzr_{x}, r_{y}, r_{z} provedením kvantové stavové tomografie pro matici hustoty ρ\rho. Vzhledem k tvaru:

ρ=12(I+rxX+ryY+rzZ)\rho = \frac{1}{2}(\textbf{I} + r_{x}\textbf{X}+ r_{y}\textbf{Y} + r_{z}\textbf{Z})

platí

Tr(Xρ)=rx,Tr(Yρ)=ry,Tr(Zρ)=rzTr(\textbf{X} \rho) = r_{x}, \quad Tr(\textbf{Y} \rho) = r_{y}, \quad Tr(\textbf{Z} \rho) = r_{z}

V případě rzr_{z}:

Tr(Zρ)=0Zρ0+1Zρ1Tr(\textbf{Z} \rho) = \langle 0|\textbf{Z} \rho|0 \rangle + \langle 1|\textbf{Z} \rho|1 \rangle =0(0011)ρ0+1(0011)ρ1= \langle 0|(|0 \rangle\langle 0|-|1 \rangle\langle 1|) \rho|0 \rangle +\langle 1|(|0 \rangle\langle 0|-|1 \rangle\langle 1|) \rho|1 \rangle =0ρ01ρ1=\langle 0|\rho|0 \rangle- \langle 1| \rho|1 \rangle =0ψψ01ψψ1=\langle 0|\psi\rangle\langle \psi|0 \rangle - \langle 1| \psi\rangle\langle \psi|1 \rangle =α2β2=|\alpha|^2-|\beta|^2

Poslední transformace rovnice platí pro ψ=α0+β1|\psi \rangle =\alpha|0\rangle+\beta|1\rangle. Hodnotu rzr_{z} tedy lze získat jako pravděpodobnost 0|0 \rangle mínus pravděpodobnost 1|1 \rangle.

Odhad hodnoty rzr_z

Abychom odhadli rzr_z, vytvoříme kvantový stav a změříme ho. Přípravu a měření pak mnohokrát zopakujeme. Nakonec využijeme statistiku měření k odhadu výše uvedených pravděpodobností, a tím odhadneme rzr_z.

Pro vytvoření náhodného kvantového stavu použijeme obecný unitární Gate UU s parametry θ,φ\theta, \varphi. (Další informace najdeš v dokumentaci U-gate.)

from qiskit import QuantumCircuit

# create a 1-qubit quantum state psi from theta, varphi parameters
qc = QuantumCircuit(1, 1)
qc.u(theta, varphi, 0.0, 0)

# measure in computational basis
qc.measure(0, 0)

qc.draw(output="mpl")

Output of the previous code cell

Pomocí AerSimulator provedeme měření ve výpočetní bázi a odhadneme rzr_z.

# see if the expected value of measuring in the computational basis
# approaches the limit of rz
from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler
from qiskit.visualization import plot_histogram

# Define backend
backend = AerSimulator()
nshots = 1000 # or 10000
# nshots = 10000

# 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], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram

plot_histogram(counts)
{'1': 375, '0': 625}

Output of the previous code cell

rz_approx = (counts["0"] - counts["1"]) / nshots

print("rz = ", rz, " and approx of rz = ", rz_approx)
rz =  0.2577405946274022  and approx of rz =  0.25

Pomocí metody kvantové stavové tomografie jsme odhadli hodnotu rzr_z. V tomto případě jsme pro „náhodný" stav zvolili parametry, takže hodnotu rzr_z známe a můžeme si výsledek ověřit. Práce v oblasti utility-scale však ze své podstaty není vždy tak snadné ověřit. O kontrole kvantových výsledků si povíme více později v tomto kurzu. Pro tuto chvíli si pouze poznamenej, že náš odhad byl přiměřeně přesný.

Cvičení 1: Odhad hodnoty rxr_x

Pamatuj si, že kvantové počítače IBM® měří podél osy zz (někdy se říká „v bázi zz" nebo „ve výpočetní bázi"). Pomocí rotací před měřením však lze měřit i projekci kvantového stavu na osu x. Přesněji řečeno, pokud náš systém otočíme tak, aby to, co mířilo podél xx, nyní mířilo podél zz, můžeme zachovat stejný měřicí hardware podél zz, ale zjistit informace o stavu, který chvíli před tím mířil podél xx. Takto většina kvantových počítačů (a všechny kvantové počítače IBM) provádí měření podél více os.

S tímto pochopením zkus napsat kód pro odhad hodnoty rxr_x pomocí kvantové stavové tomografie.

Řešení:

# create a 1-qubit quantum state psi from theta, varphi parameters
qc = QuantumCircuit(1, 1)
qc.u(theta, varphi, 0.0, 0)

qc.h(0)
qc.measure(0, 0)

qc.draw(output="mpl")

Output of the previous code cell

# Define backend
backend = AerSimulator()
nshots = 10000

# 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], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'1': 5925, '0': 4075}

Output of the previous code cell

rx_approx = (counts["0"] - counts["1"]) / nshots

print("rx = ", rx, " and approx of rx = ", rx_approx)
rx =  -0.1791150283307452  and approx of rx =  -0.185

Cvičení 2: Odhad hodnoty ryr_y

Pomocí stejných logických argumentů jako dříve lze systém před měřením otočit a zjistit tak informace o ryr_y. Zkus sám napsat kód pro odhad hodnoty ryr_y pomocí kvantové stavové tomografie. Můžeš vycházet z předchozího příkladu, ale použít jiné rotace. (Další informace o různých Gates, včetně sdg, najdeš v referenční příručce API.)

Řešení:

# create a 1-qubit quantum state psi from theta, varphi parameters
qc = QuantumCircuit(1, 1)
qc.u(theta, varphi, 0.0, 0)

qc.sdg(0)
qc.h(0)
qc.measure(0, 0)

qc.draw(output="mpl")

Output of the previous code cell

# Define backend
backend = AerSimulator()
nshots = 10000

# 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], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'1': 9759, '0': 241}

Output of the previous code cell

ry_approx = (counts["0"] - counts["1"]) / nshots

print("ry = ", ry, " and approx of ry = ", ry_approx)
ry =  -0.9494670044331133  and approx of ry =  -0.9518

Nyní jsme odhadli všechny složky r\vec{r} a můžeme zapsat celý vektor.

print("Estimated vector is (", rx_approx, ",", ry_approx, ",", rz_approx, ").")
print("Original random vector was (" + str(rx) + ", " + str(ry) + ", " + str(rz) + ").")
Estimated vector is ( -0.185 , -0.9518 , 0.25 ).
Original random vector was (-0.1791150283307452, -0.9494670044331133, 0.2577405946274022).

Pomocí této metody kvantové stavové tomografie jsi získal/a poměrně přesný odhad původního náhodného vektoru.

4. Kvantová teleportace

Představme si situaci, kdy chce postava Alice poslat neznámý kvantový stav ψ|\psi \rangle svému příteli Bobovi, který je daleko. Předpokládejme, že mohou komunikovat pouze klasickou komunikací (například e-mailem nebo telefonem). Alice nemůže kvantový stav zkopírovat (kvůli teorému o neklonování). Kdyby opakovala stejný přípravný proces mnohokrát, mohla by budovat statistiku, jako jsme to právě dělali. Ale co když existuje pouze jediný neznámý stav? Tento stav mohl vzniknout z fyzikálního procesu, který chceš studovat. Nebo může být součástí rozsáhlejšího kvantového výpočtu. V takovém případě, jak by Alice mohla poslat stav Bobovi? Může – pokud ona a Bob sdílejí cenný kvantový zdroj: sdílený provázaný stav, jako je Bellův stav představený v předchozí lekci: 00+112.\frac {|00\rangle + |11\rangle}{\sqrt 2}. Někdy se na tento stav odkazuje také jako na „EPR pár" nebo „e-bit" (základní jednotka provázanosti). Pokud Alice sdílí takový provázaný stav s Bobem, může neznámý kvantový stav teleportovat k Bobovi provedením série kvantových operací a zasláním dvou bitů klasické informace.

4.1 Protokol kvantové teleportace

Předpoklad: Alice má neznámý kvantový stav ψ|\psi \rangle, který má odeslat Bobovi. Alice a Bob sdílejí 2-qubitový provázaný stav neboli e-bit; každý z nich má fyzicky u sebe jeden z qubitů.

Zde nastiňujeme postup bez vysvětlení. Níže bude vše podrobně implementováno.

  1. Alice provázáže ψ|\psi \rangle se svou částí e-bitu pomocí Gate CNOT.
  2. Alice aplikuje Gate Hadamard na ψ|\psi \rangle a měří oba své qubity ve výpočetní bázi.
  3. Alice pošle Bobovi výsledky svého měření (buď „00", „01", „10", nebo „11").
  4. Bob provede korekční operátor na základě dvoubitové informace od Alice na své části e-bit páru.
    • Pokud „00", Bob nedělá nic.
    • Pokud „01", Bob aplikuje Gate X.
    • Pokud „10", Bob aplikuje Gate Z.
    • Pokud „11", Bob aplikuje iY = ZX gate.
  5. Bobova část e-bitu se stane ψ|\psi \rangle.

Toto je také podrobněji zpracováno v části Základy kvantové informace. Situace se ale objasní, jakmile to implementujeme v Qiskitu.

4.2 Kvantový Circuit simulující kvantovou teleportaci

Jako vždy použijeme framework Qiskit patterns. Tato podsekce se zaměří pouze na mapování.

Krok 1: Namapuj problém na kvantové Circuits a operátory

Abychom popsali výše uvedený scénář, potřebujeme Circuit se třemi qubity: dva pro provázaný pár sdílený Alicí a Bobem a jeden pro neznámý kvantový stav ψ|\psi\rangle.

from qiskit import QuantumCircuit
import numpy as np
# create 3-qubits circuit
qc = QuantumCircuit(3, 3)

qc.draw(output="mpl")

Output of the previous code cell

Na začátku má Alice neznámý kvantový stav ψ.|\psi \rangle. Vytvoříme ho pomocí Gate UU.

# Create the unknown quantum state using the u-gate. Alice has this.
qc.u(theta, varphi, 0.0, 0)
qc.barrier() # for visual separation

qc.draw(output="mpl")

Output of the previous code cell

Stav, který jsme vytvořili, si můžeme vizualizovat – ale jen proto, že víme, jaké parametry byly použity v Gate UU. Kdyby tento stav vznikl z komplikovaného kvantového procesu, nebylo by možné stav zjistit bez toho, abychom proces spustili mnohokrát a sbírali statistiky jako při tomografii.

# show the quantum state on bloch sphere
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector

out_vector = Statevector(qc)

plot_bloch_multivector(out_vector)

Output of the previous code cell

Ještě před zahájením tohoto protokolu předpokládáme, že Alice a Bob mají sdílený provázaný pár. Pokud se Alice a Bob skutečně nacházejí na různých místech, mohli sdílený stav nastavit předtím, než byl neznámý stav ψ|\psi\rangle vůbec vytvořen. Protože tyto věci probíhají na různých qubitech, na jejich pořadí nezáleží, a toto pořadí je pohodlné pro vizualizaci.

# Alice and Bob are together in the same place and set up an entangled pair.
qc.h(1)
qc.cx(1, 2)
qc.barrier() # for visual separation.
# We can consider that Alice and Bob might move their qubits to different physical locations, now.

qc.draw(output="mpl")

Output of the previous code cell

Dále Alice provázáže ψ|\psi \rangle se svou částí sdíleného e-bitu pomocí Gate CXCX a Gate HH a měří je ve výpočetní bázi.

# Alice entangles the unknown state with her part of the e-bit, using the CNOT gate and H gate.
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Alice measures the two qubits.
qc.measure(0, 0)
qc.measure(1, 1)

qc.draw(output="mpl")

Output of the previous code cell

Alice pošle Bobovi výsledky svého měření (buď „00", „01", „10", nebo „11") a Bob provede korekční operátor na základě dvou bitů informace od Alice na své části sdíleného e-bitu. Poté se Bobova část stane ψ|\psi \rangle.

# Alice sent the results to Bob. Bob applies correction
with qc.if_test((0, 1)):
qc.z(2)
with qc.if_test((1, 1)):
qc.x(2)
qc.barrier()

qc.draw(output="mpl")

Output of the previous code cell

Dokončil/a jsi Circuit kvantové teleportace! Podívejme se na výstupní stav tohoto Circuitu pomocí simulátoru statevector.

from qiskit_aer import StatevectorSimulator

backend = StatevectorSimulator()
out_vector = backend.run(qc, shots=1).result().get_statevector() # set shots = 1

plot_bloch_multivector(out_vector)

Output of the previous code cell

Vidíš, že kvantový stav vytvořený Gate UU qubitu 0 (qubit původně držící tajný stav) byl přenesen na qubit 2 (Bobův qubit).

Výše uvedenou buňku můžeš spustit několikrát, abys to ověřil/a. Možná si všimneš, že qubity 0 a 1 mění stavy, ale qubit 2 je vždy ve stavu ψ|\psi\rangle.

4.3 Spusť to a ověř výsledek aplikováním inverzního U

Výše jsme vizuálně ověřili, že teleportovaný stav vypadá správně. Dalším způsobem, jak zkontrolovat, zda byl kvantový stav teleportován správně, je aplikovat inverzní Gate UU na Bobův Qubit a změřit '0'. Protože U1UU^{-1}U je identita, pokud je Bobův Qubit ve stavu vytvořeném z U0,U|0\rangle, pak by aplikace inverze měla dát U1U0=0.U^{-1}U|0\rangle=|0\rangle.

# Apply the inverse of u-gate to measure |0>
qc.u(theta, varphi, 0.0, 2).inverse() # inverse of u(theta,varphi,0.0)
qc.measure(2, 2) # add measurement gate

qc.draw(output="mpl")

Output of the previous code cell

Nejprve spustíme Circuit pomocí AerSimulator, než přejdeme na skutečný kvantový počítač.

from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler
from qiskit.visualization import plot_histogram

# 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], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'011': 2510, '010': 2417, '000': 2635, '001': 2438}

Output of the previous code cell

Připomeňme, že v notaci little endian je Qubit 2 zcela vlevo (nebo zcela dole ve sloupcových popisech). Všimni si, že Qubit zcela vlevo a dole ve sloupcových popisech je 0 pro všechny možné výsledky. To ukazuje, že máme 100% šanci naměřit q2q_2 ve stavu 0|0\rangle . Toto je očekávaný výsledek a potvrzuje, že teleportační protokol fungoval správně.

4.4 Teleportace na skutečném kvantovém počítači

Nyní provedeme teleportaci na skutečném kvantovém počítači. Pomocí funkce dynamického Circuit můžeme uprostřed Circuit pracovat s výsledky měření a v reálném čase implementovat podmíněné operace v teleportačním Circuit. Při řešení problémů se skutečnými kvantovými počítači budeme postupovat podle čtyř kroků vzorů Qiskit.

  1. Namapuj problém na kvantové Circuit a operátory
  2. Optimalizuj pro cílový hardware
  3. Spusť na cílovém hardwaru
  4. Zpracuj výsledky

Cvičení 3: Sestav teleportační Circuit

Zkus sestavit celý teleportační Circuit od začátku a otestuj své porozumění. Pokud potřebuješ připomenout postup, posuň se zpět nahoru.

Řešení:

# Step 1: Map problem to quantum circuits and operators
# Create the circuit with 3-qubits and 1-bit
qc = QuantumCircuit(3, 3)

# Alice creates an unknown quantum state using the u-gate.
qc.u(theta, varphi, 0.0, 0)
qc.barrier() # for visual separation

# Eve creates EPR pair and sends q1 to Alice and q2 to Bob
##your code goes here##
qc.h(1)
qc.cx(1, 2)
qc.barrier()

# Alice entangles the unknown state with her EPR part, using the CNOT gate and H gate.
##your code goes here##
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Alice measures the two qubits.
##your code goes here##
qc.measure(0, 0)
qc.measure(1, 1)

# Alice sent the results to Bob. Now, Bob applies correction
##your code goes here##
with qc.if_test((0, 1)):
qc.z(2)
with qc.if_test((1, 1)):
qc.x(2)
qc.barrier()

# Apply the inverse of u-gate to measure |0>
qc.u(theta, varphi, 0.0, 2).inverse()
qc.measure(2, 2)

qc.draw(output="mpl")

Output of the previous code cell

Připomínáme, že aplikace inverzního Gate UU slouží pouze k ověření očekávaného chování. Není součástí přenosu stavu k Bobovi a nepoužili bychom tento inverzní Gate UU, pokud by jediným cílem byl přenos kvantové informace.

Krok 2: Optimalizace pro cílový hardware

Pro spuštění na hardwaru naimportuj QiskitRuntimeService a načti uložená přihlašovací údaje. Vyber Backend s nejmenším počtem úloh ve frontě.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
service.backends()
[<IBMBackend('ibm_brisbane')>,
<IBMBackend('ibm_torino')>]
# You can also identify the least busy device
backend = service.least_busy(operational=True)
print("The least busy device is ", backend)
The least busy device is  <IBMBackend('ibm_brisbane')>
# You can specify the device
# backend = service.backend('ibm_brisbane')

Podívejme se na mapu propojení vybraného zařízení.

from qiskit.visualization import plot_gate_map

plot_gate_map(backend)

Output of the previous code cell

Různá zařízení mohou mít různé mapy propojení a každé zařízení má Qubity a spoje, které jsou výkonnější než ostatní. A konečně, různé kvantové počítače mohou mít různé nativní Gate (Gate, které hardware dokáže přímo spustit). Transpilace obvodu přepíše abstraktní kvantový Circuit pomocí Gate, které cílový kvantový počítač dokáže spustit, a zvolí optimální mapování na fyzické Qubity (mimo jiné). Transpilace je obsáhlé a složité téma. Více informací o transpilaci najdeš v referenci API.

# Step 2: Optimize for target hardware
# Transpile the circuit into basis gates executable on the hardware
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
qc_compiled = pm.run(qc)

qc_compiled.draw("mpl", idle_wires=False, fold=-1)

Output of the previous code cell

Krok 3: Spuštění Circuit.

Pomocí primitiva Runtime Sampler spustíme cílový Circuit.

# Step 3: Execute the target circuit
sampler = Sampler(backend)
job = sampler.run([qc_compiled])
job_id = job.job_id()
print("job id:", job_id)
job id: d13nkhpn2txg008jt0d0
# Check the job status
job.status()
'DONE'

Stav úlohy můžeš také zkontrolovat ve svém dashboardu IBM Quantum®.

# 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.job_id()) # Input your job-id between the quotations
job_real.status()
'DONE'

Pokud se zobrazí 'DONE', výsledek získáš spuštěním níže uvedené buňky.

# Execute after 'DONE' is displayed
result_real = job_real.result()
print(result_real[0].data.c.get_counts())
{'001': 992, '110': 430, '011': 579, '010': 605, '111': 402, '000': 925, '100': 57, '101': 106}

Krok 4: Následné zpracování výsledků

# Step 4: Post-process the results
from qiskit.visualization import plot_histogram

plot_histogram(result_real[0].data.c.get_counts())

Output of the previous code cell

Výše uvedené výsledky můžeš interpretovat přímo. Nebo pomocí marginal_count můžeš vysledovat výsledky Boba na Qubitu 2.

# trace out Bob's results on qubit 2
from qiskit.result import marginal_counts

bobs_qubit = 2
real_counts = result_real[0].data.c.get_counts()
bobs_counts = marginal_counts(real_counts, [bobs_qubit])
plot_histogram(bobs_counts)

Output of the previous code cell

Jak vidíme, v několika výsledcích jsme naměřili 1|1 \rangle. Tyto odchylky jsou způsobeny šumem a chybami. Dynamické Circuit mají zejména vyšší míru chyb kvůli časově náročnému měření uprostřed obvodu.

4.5 Klíčové poznatky o kvantové teleportaci

Kvantový stav můžeme přenést vzdálenému příteli sdílením páru propletených Qubitů (e-bit).

  1. Může kvantová teleportace přenést kvantový stav rychleji než světlo? Ne, protože Alice musí Bobovi sdělit výsledky měření klasickým způsobem.

  2. Porušovala by kvantová teleportace „teorém o neklonování", který zakazuje kopírování kvantového stavu? Ne, protože původní kvantový stav, který měla Alice na jednom ze svých Qubitů, byl při měření ztracen. Kolapsem přešel do stavu 0|0\rangle nebo 1|1\rangle.

5. Superdense kódování

Téměř stejné uspořádání lze použít i pro jiný účel. Předpokládejme, že Alice chce Bobovi poslat dva bity klasických informací, ale nemá s Bobem žádný způsob klasické komunikace. Sdílí však s Bobem provázaný pár a může svůj qubit odeslat na Bobovo místo. Všimni si kontrastu s protokolem kvantové teleportace. Při teleportaci byla klasická komunikace přátelům k dispozici a cílem bylo odeslat kvantový stav. Zde klasická komunikace dostupná není a k předání dvou bitů klasických informací se využívá přenos qubitu.

5.1 Protokol superdense kódování

Předpoklad: Alice má dva bity informace, řekněme a1a2{00,01,10,11}a_1a_2 \in \{00, 01, 10, 11\}. Alice a Bob sdílí provázaný pár (e-bit), ale nemohou klasicky komunikovat.

  1. Alice provede jednu z následujících operací na své části e-bitu.
    • Pokud a1a2=00a_1a_2 = 00, nedělá nic
    • Pokud a1a2=01a_1a_2 = 01, aplikuje Gate Z
    • Pokud a1a2=10a_1a_2 = 10, aplikuje Gate X
    • Pokud a1a2=11a_1a_2 = 11, aplikuje Gate Z a Gate X.
  2. Alice pošle svou část e-bitu na Bobovo místo.
  3. Bob aplikuje Gate CNOT s qubitem od Alice jako řídicím a svým qubitem jako cílovým, poté aplikuje Gate H na qubit od Alice a změří oba qubity. Možné počáteční stavy a výsledky Bobových operací jsou:
00+112CX01H000\frac {|00\rangle + |11\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |00\rangle 00112CX01H001\frac {|00\rangle - |11\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |01\rangle 10+012CX01H010\frac {|10\rangle + |01\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |10\rangle 10012CX01H011\frac {|10\rangle - |01\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow -|11\rangle

Všimni si, že záporné znaménko 11-|11\rangle je globální fáze, takže ji nelze změřit.

5.2 Kvantový Circuit simulující superdense kódování

Na základě protokolu superdense kódování můžeš sestavit Circuit superdense kódování níže. Zkus změnit zprávu, msg, kterou chce Alice přenést Bobovi.

from qiskit import QuantumCircuit

Kroky vzoru Qiskit jsou označeny v komentářích kódu.

# Step 1: Map problem to quantum circuits and operators
# Create 2-qubits circuit
qc = QuantumCircuit(2, 2)

# Eve creates EPR pair and send q0 to Alice and q1 to Bob
qc.h(0)
qc.cx(0, 1)
qc.barrier()

# set message which Alice wants to transform to Bob
msg = "11" # You can change the message

if msg == "00":
pass
elif msg == "10":
qc.x(0)
elif msg == "01":
qc.z(0)
elif msg == "11":
qc.z(0)
qc.x(0)

qc.barrier()
# Bob receives EPR qubit from Alice and performs unitary operations
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Bob measures q0 and q1
qc.measure(0, 0)
qc.measure(1, 1)

qc.draw(output="mpl")

Výstup předchozí buňky kódu

# We will execute on a simulator first
from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler

# Define backend
backend = AerSimulator()
shots = 1000

# 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_sim = sampler.run([isa_qc], shots=shots)
result_sim = job_sim.result()

# Extract counts data
counts = result_sim[0].data.c.get_counts()
print(counts)
{'11': 1000}
# Visualize the results
from qiskit.visualization import plot_histogram

plot_histogram(counts)

Výstup předchozí buňky kódu

Vidíš, že Bob přijal zprávu, kterou mu Alice chtěla poslat.

Teď to zkusme na skutečném kvantovém počítači.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.least_busy(operational=True)
print("The least busy device is ", backend)
The least busy device is  <IBMBackend('ibm_brisbane')>
# Step 1 was already completed before the simulator job above.
# Step 2: Optimize for target hardware
# Transpile the circuit into basis gates executable on the hardware
pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
qc_compiled = pm.run(qc)

qc_compiled.draw("mpl", idle_wires=False)

Výstup předchozí buňky kódu

# Step 3:Execute the target circuit
sampler = Sampler(backend)
job = sampler.run([qc_compiled])
job_id = job.job_id()
print("job id:", job_id)
job id: d13nnyq3grvg008j0zag
# Check the job status
job.status()
'DONE'
# 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 = service.job(job_id) # Input your job-id between the quotations
job.status()
'DONE'
# Execute after job has successfully run
real_result = job.result()
print(real_result[0].data.c.get_counts())
{'11': 3942, '01': 107, '10': 41, '00': 6}
# Step 4: post-process the results
from qiskit.visualization import plot_histogram

plot_histogram(real_result[0].data.c.get_counts())

Výstup předchozí buňky kódu

Výsledek je takový, jaký jsme očekávali. Všimni si, že superdense kódování na skutečném kvantovém počítači vykazovalo méně chyb než kvantová teleportace na skutečném kvantovém počítači. Jedním z důvodů může být, že kvantová teleportace využívá dynamické Circuity, zatímco superdense kódování ne. O chybách v kvantových Circuitech se dozvíme více v dalších lekcích.

6. Shrnutí

V této lekci jsme implementovali dva kvantové protokoly. Ačkoli jsou scénáře pro oba protokoly zahrnující vzdálené přátele poněkud vzdálené od kvantových výpočtů na jednom QPU, mají uplatnění v kvantových výpočtech a pomáhají nám lépe pochopit přenos kvantových informací.

  • Kvantová teleportace: Přestože nemůžeme kopírovat kvantové stavy, můžeme přenášet neznámé kvantové stavy díky sdílenému provázání.
  • Kvantové superdense kódování: Sdílený provázaný pár a přenos jednoho qubitu umožňují komunikaci dvou bitů klasických informací.
# See the version of Qiskit
import qiskit

qiskit.__version__
'2.0.2'