Sari la conținutul principal

Teleportare cuantică și codificare supradensă

notă

Kifumi Numata (26 Apr 2024)

Descarcă pdf-ul al lecției originale. Reține că unele fragmente de cod ar putea deveni depreciate, deoarece sunt imagini statice.

Timpul aproximativ de QPU pentru a rula acest experiment este de 10 secunde.

1. Introducere

Pentru a rezolva orice problemă cuantică la scară utilitară, va trebui să mutăm informații pe un computer cuantic dintr-un qubit în altul. Există protocoale bine cunoscute pentru a face asta, dar unele dintre cele mai fundamentale au fost formulate în contextul trimiterii de informații între părți aflate la distanță. Pe tot parcursul acestei lecții, vom folosi uneori un limbaj consistent cu acest context, cum ar fi „prieteni aflați la distanță care își trimit informații". Dar ține minte că aceste protocoale au o semnificație mai largă în calculul cuantic. În această lecție, luăm în considerare următoarele protocoale de comunicare cuantică:

  • Teleportare cuantică Folosirea unui stat entanglat partajat (uneori numit e-bit) pentru a trimite un stat cuantic necunoscut unui prieten aflat la distanță, necesitând comunicare clasică suplimentară.
  • Codificare cuantică supradensă Cum să trimiți două biți de informație prin trimiterea unui singur qubit unui prieten aflat la distanță (din nou folosind qubiți entanglați partajați în prealabil).

Pentru mai mult context relevant acestor subiecte, îți recomandăm lecția 4 din Bazele Informației Cuantice despre Entanglement în acțiune.

În descrierea de mai sus, un „stat cuantic necunoscut" se referă pur și simplu la un stat de forma descrisă în lecția anterioară:

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

unde α\alpha și β\beta sunt numere complexe astfel încât α2+β2=1|\alpha|^2+|\beta|^2 = 1. Acest lucru ne permite să scriem statul cuantic ca

ψ=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)

Deoarece vrem să putem transfera informația dintr-un stat cuantic arbitrar, generarea unui astfel de stat este de unde vom începe această lecție.

2. Matrici de densitate

Putem scrie și statul cuantic ψ|\psi \rangle ca matrice de densitate. Această formă este utilă pentru a nota amestecul probabilistic de stări cuantice pure. În cazul unui singur qubit, putem scrie

ψψρ=((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)

Observă că matricea de densitate ρ\rho este o sumă liniară de matrice Pauli, după cum urmează:

ρ=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)

Sau, în general,

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

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

Și, vectorul Bloch este r=(rx,ry,rz)\textbf{r} = (r_{x}, r_{y}, r_{z}).

Acum, hai să construim un stat cuantic arbitrar folosind numere aleatoare.

# 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)

Putem afișa acest vector Bloch pe sfera Bloch.

from qiskit.visualization import plot_bloch_vector

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

Output of the previous code cell

3. Tomografia statului cuantic

Dacă măsori statul cuantic doar în baza computațională (0|0 \rangle și 1|1 \rangle), informația de fază (informația despre numerele complexe) se va pierde. Dar dacă avem multe copii ale lui ψ|\psi \rangle prin repetarea procesului de pregătire (nu putem clona stările, dar putem repeta procesele de pregătire), putem estima valoarea lui rx,ry,rzr_{x}, r_{y}, r_{z} efectuând tomografia statului cuantic pentru matricea de densitate ρ\rho. Dată forma:

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

este adevărat că

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}

În cazul 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

Ultima transformare a ecuației este pentru ψ=α0+β1|\psi \rangle =\alpha|0\rangle+\beta|1\rangle. Prin urmare, putem obține rzr_{z} ca probabilitate de 0|0 \rangle - Probabilitate de 1|1 \rangle.

Estimarea valorii rzr_z

Pentru a estima rzr_z, creăm un stat cuantic și îl măsurăm. Repetăm apoi procesul de pregătire și măsurare de mai multe ori. În final, folosim statisticile măsurătorilor pentru a estima probabilitățile de mai sus și, astfel, a estima rzr_z.

Pentru a crea statul cuantic aleator, vom folosi Gate-ul unitar general UU cu parametrii θ,φ \theta, \varphi. (Consultați U-gate pentru mai multe informații.)

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

Folosind AerSimulator, vom măsura în baza computațională pentru a estima 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

Folosind metoda tomografiei statului cuantic, am estimat valoarea rzr_z. În acest caz, deoarece am ales un parametru pentru statul „aleator", cunoaștem valoarea lui rzr_z și putem verifica rezultatul. Dar prin natura sa, munca la scară utilitară nu este întotdeauna atât de trivial de verificat. Vom discuta mai mult despre verificarea rezultatelor cuantice mai târziu în acest curs. Deocamdată, observă pur și simplu că estimarea noastră a fost rezonabil de precisă.

Exercițiul 1: Estimarea valorii rxr_x

Reamintește-ți că computerele cuantice IBM® măsoară de-a lungul axei zz (uneori formulat „în baza zz" sau „în baza computațională"). Totuși, folosind rotații înainte de măsurare, putem măsura și proiecția statului cuantic pe axa x. Mai precis, dacă rotim sistemul nostru astfel încât lucrurile care indicau anterior spre xx să indice acum spre zz, atunci putem păstra același hardware de măsurare de-a lungul lui zz, dar să aflăm informații despre statul care tocmai indica spre xx cu puțin timp în urmă. Acesta este modul în care majoritatea computerelor cuantice (și toate computerele cuantice IBM) efectuează măsurători de-a lungul mai multor axe.

Cu această înțelegere, încearcă să scrii cod pentru a estima valoarea lui rx,r_x, folosind tomografia statului cuantic.

Soluție:

# 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

Exercițiul 2: Estimarea valorii ryr_y

Folosind aceleași argumente logice ca mai înainte, putem roti sistemul înainte de măsurare pentru a afla informații despre ryr_y. Încearcă să scrii cod singur pentru a estima valoarea lui ryr_y folosind tomografia statului cuantic. Poți porni de la exemplul anterior, dar aplică rotații diferite. (Pentru mai multe informații despre diferitele Gate-uri folosite, inclusiv sdg, consultați referința API.)

Soluție:

# 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

Am estimat acum toate componentele lui r\vec{r} și putem scrie vectorul complet.

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).

Ai obținut estimarea vectorului aleator original cu o precizie rezonabilă folosind această metodă de tomografie a statului cuantic.

4. Teleportare cuantică

Să considerăm situația în care Alice vrea să trimită un stat cuantic necunoscut ψ|\psi \rangle prietenului ei Bob, care se află departe. Presupune că pot comunica doar prin comunicare clasică (cum ar fi e-mail sau telefon). Alice nu poate copia statul cuantic (din cauza teoremei no-cloning). Dacă ar repeta același proces de pregătire de mai multe ori, ar putea construi statistici, cum am făcut chiar acum. Dar ce se întâmplă dacă există un singur stat necunoscut? Acest stat ar fi putut apărea dintr-un proces fizic pe care vrei să îl studiezi. Sau ar putea face parte dintr-un calcul cuantic mai mare. În acest caz, cum ar putea Alice să trimită statul lui Bob? Poate, dacă ea și Bob împart o resursă cuantică valoroasă: un stat entanglat partajat, precum statul Bell introdus în lecția anterioară: 00+112.\frac {|00\rangle + |11\rangle}{\sqrt 2}. S-ar putea să mai auzi că acesta este denumit „pereche EPR" sau „e-bit" (o unitate fundamentală de entanglement). Dacă Alice împarte un astfel de stat entanglat cu Bob, ea poate teleporta statul cuantic necunoscut la Bob efectuând o serie de operații cuantice și trimițându-i două biți de informație clasică.

4.1 Protocolul de teleportare cuantică

Presupunere: Alice are un stat cuantic necunoscut ψ|\psi \rangle care trebuie trimis lui Bob. Alice și Bob împart un stat entanglat de 2 qubiți, sau e-bit, fiecare având unul dintre qubiți fizic la locația lor.

Iată procedura fără explicații. Acestea vor fi implementate în detaliu mai jos.

  1. Alice entanglează ψ|\psi \rangle cu partea sa din e-bit folosind Gate-ul CNOT.
  2. Alice aplică un Gate Hadamard lui ψ|\psi \rangle și măsoară ambii qubiți ai săi în baza computațională.
  3. Alice îi trimite lui Bob rezultatele măsurătorilor ei (fie „00", „01", „10" sau „11")
  4. Bob efectuează un operator de corecție bazat pe cei doi biți de informație ai lui Alice pe partea lui din perechea e-bit.
    • Dacă „00", Bob nu face nimic
    • Dacă „01", Bob aplică Gate X
    • Dacă „10", Bob aplică Gate Z
    • Dacă „11", Bob aplică iY = ZX Gate
  5. Partea lui Bob din e-bit devine ψ|\psi \rangle.

Aceasta este elaborată și mai detaliat în Bazele Informației Cuantice. Dar situația va deveni mai clară pe măsură ce o instanțiem în Qiskit.

4.2 Circuit cuantic care simulează teleportarea cuantică

Ca întotdeauna, vom aplica framework-ul Qiskit patterns. Această subsecțiune se va concentra doar pe mapare.

Pasul 1: Maparea problemei la circuite și operatori cuantici

Pentru a descrie scenariul de mai sus, avem nevoie de un Circuit cu trei qubiți: doi pentru perechea entanglată partajată de Alice și Bob, și unul pentru statul cuantic necunoscut ψ|\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

La început, Alice are un stat cuantic necunoscut ψ.|\psi \rangle. Îl vom crea folosind Gate-ul 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

Putem vizualiza statul pe care l-am creat, dar numai pentru că știm ce parametri au fost folosiți în Gate-ul UU. Dacă acest stat ar fi apărut dintr-un proces cuantic complicat, statul nu ar fi cognoscibil fără a rula procesul de mai multe ori și a colecta statistici ca în tomografie.

# 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

Înainte ca acest protocol să înceapă, presupunem că Alice și Bob au o pereche entanglată partajată. Dacă Alice și Bob se află cu adevărat în locații diferite, ar fi putut configura statul partajat înainte ca statul necunoscut ψ|\psi\rangle să fi fost creat vreodată. Deoarece acele lucruri se întâmplă pe qubiți diferiți, ordinea lor nu va conta, iar această ordine este convenabilă pentru vizualizare.

# 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

Apoi, Alice entanglează ψ|\psi \rangle cu partea sa din e-bit-ul partajat, folosind Gate-ul CXCX și Gate-ul HH, și le măsoară în baza computațională.

# 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 îi trimite lui Bob rezultatele măsurătorilor ei (fie „00", „01", „10" sau „11"), iar Bob efectuează un operator de corecție bazat pe cei doi biți de informație ai lui Alice pe partea sa din e-bit-ul partajat. Apoi, qubit-ul lui Bob devine ψ|\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

Ai finalizat un Circuit de teleportare cuantică! Hai să vedem statul de ieșire al acestui Circuit folosind simulatorul de vector de stare.

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

Poți vedea că statul cuantic creat de Gate-ul UU al qubit-ului 0 (qubit-ul care deținea inițial statul secret) a fost transferat la qubit-ul 2 (qubit-ul lui Bob).

Poți rula celula de mai sus de câteva ori pentru a te asigura. S-ar putea să observi că qubiții 0 și 1 își schimbă stările, dar qubit-ul 2 este întotdeauna în statul ψ|\psi\rangle .

4.3 Execuție și confirmarea rezultatului prin aplicarea inversului lui U

Mai sus, am verificat vizual că statul teleportat arăta corect. O altă modalitate de a verifica dacă statul cuantic a fost teleportat corect este să aplici inversul Gate-ului UU pe qubit-ul lui Bob, astfel încât să putem măsura „0". Adică, deoarece U1UU^{-1}U este identitatea, dacă qubit-ul lui Bob se află în statul creat din U0,U|0\rangle, atunci aplicarea inversului ar trebui să producă 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

Vom executa Circuit-ul mai întâi folosind AerSimulator, înainte de a trece la un computer cuantic real.

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

Reamintește-ți că în notația little endian, qubit-ul 2 este cel mai din stânga (sau cel mai de jos, în etichetele coloanelor). Observă că qubit-ul cel mai din stânga și cel mai de jos din etichetele coloanelor este 0 pentru toate rezultatele posibile. Asta arată că avem o șansă de 100% de a măsura q2q_2 în statul 0|0\rangle . Acesta este rezultatul așteptat și indică faptul că protocolul de teleportare a funcționat corect.

4.4 Teleportare pe un computer cuantic real

Acum, vom efectua teleportarea pe un computer cuantic real. Folosind funcția de circuit dinamic, putem opera la mijlocul circuit-ului folosind rezultatele măsurătorilor, implementând în timp real operațiile condiționale din Circuit-ul de teleportare. Pentru a rezolva probleme cu computere cuantice reale, vom urma cei patru pași ai Qiskit patterns.

  1. Mapează problema la circuite și operatori cuantici
  2. Optimizează pentru hardware-ul țintă
  3. Execută pe hardware-ul țintă
  4. Post-procesează rezultatele

Exercițiul 3: Construiește Circuit-ul de teleportare

Încearcă să construiești întregul Circuit de teleportare de la zero pentru a-ți testa înțelegerea. Derulează în sus dacă ai nevoie de un memento.

Soluție:

# 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

Ca memento, aplicarea inversului Gate-ului UU este doar pentru a putea verifica comportamentul așteptat. Nu face parte din trimiterea statului lui Bob, și nu am folosi acel Gate UU invers dacă singurul scop ar fi transferul informației cuantice.

Pasul 2: Optimizare pentru hardware-ul țintă

Pentru a rula pe hardware, importă QiskitRuntimeService și încarcă acreditările salvate. Selectează Backend-ul cu cel mai mic număr de job-uri în coadă.

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')

Hai să vedem harta de cuplare a dispozitivului pe care l-ai selectat.

from qiskit.visualization import plot_gate_map

plot_gate_map(backend)

Output of the previous code cell

Dispozitivele diferite pot avea hărți de cuplare diferite, iar fiecare dispozitiv are unii qubiți și cuplori mai performanți decât alții. În plus, diferite computere cuantice ar putea avea gate-uri native diferite (gate-uri pe care hardware-ul le poate executa). Transpilarea Circuit-ului rescrie Circuit-ul cuantic abstract folosind gate-uri pe care computerul cuantic țintă le poate executa și selectează maparea optimă la qubiți fizici (printre altele). Transpilarea este un subiect bogat și complex. Pentru mai multe informații despre transpilare, consultați referința 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

Pasul 3: Execuția Circuit-ului.

Folosind primitiva Runtime Sampler, vom executa Circuit-ul țintă.

# 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'

Poți verifica și statusul job-ului din tabloul de bord 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'

Dacă vezi că se afișează 'DONE', poți obține rezultatul executând celula de mai jos.

# 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}

Pasul 4: Post-procesarea rezultatelor

# 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

Poți interpreta rezultatele de mai sus direct. Sau, folosind marginal_count, poți extrage rezultatele lui Bob pe qubit-ul 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

Cum vedem aici, există câteva rezultate în care am măsurat 1|1 \rangle. Acestea se datorează zgomotului și erorilor. În special, circuitele dinamice tind să aibă o rată de eroare mai mare din cauza măsurătorilor consumatoare de timp la mijlocul Circuit-ului.

4.5 Concluzii cheie despre teleportarea cuantică

Putem transporta un stat cuantic unui prieten aflat la distanță prin partajarea unei perechi de qubiți entanglați (un e-bit).

  1. Poate teleportarea cuantică trimite statul cuantic mai rapid decât lumina? Nu, pentru că Alice trebuie să îi comunice lui Bob rezultatele măsurătorilor în mod clasic.

  2. Ar încălca teleportarea cuantică „teorema no-cloning", care interzice copierea unui stat cuantic? Nu, pentru că statul cuantic original dat lui Alice pe unul dintre qubiții ei s-a pierdut în măsurătoare. S-a colaps la 0|0\rangle sau 1|1\rangle.

5. Codificare supradensă

Aproape același setup poate fi folosit pentru un scop diferit. Presupune că Alice vrea să îi trimită lui Bob doi biți de informație clasică, dar nu are niciun mijloc de comunicare clasică cu Bob. Ea împarte, totuși, o pereche entanglată cu Bob și i se permite să trimită qubit-ul ei la locația lui Bob. Observă contrastul cu protocolul de teleportare cuantică. În teleportare, comunicarea clasică era disponibilă prietenilor, iar scopul era trimiterea unui stat cuantic. Aici, comunicarea clasică nu este accesibilă și ei folosesc transferul unui qubit pentru a partaja doi biți de informație clasică.

5.1 Protocolul de codificare supradensă

Presupunere: Alice are doi biți de informație, să zicem, a1a2{00,01,10,11}a_1a_2 \in \{00, 01, 10, 11\}. Alice și Bob împart o pereche entanglată (e-bit), dar nu pot comunica clasic.

  1. Alice efectuează una dintre operațiile următoare pe partea ei din e-bit.
    • Dacă a1a2=00a_1a_2 = 00, nu face nimic
    • Dacă a1a2=01a_1a_2 = 01, aplică Gate Z
    • Dacă a1a2=10a_1a_2 = 10, aplică Gate X
    • Dacă a1a2=11a_1a_2 = 11, aplică Gate Z și Gate X.
  2. Alice trimite partea sa din e-bit la locația lui Bob.
  3. Bob aplică un Gate CNOT cu qubit-ul de la Alice ca control și qubit-ul său ca țintă, apoi aplică Gate H qubit-ului de la Alice, și măsoară cei doi qubiți. Stările inițiale posibile și rezultatele operațiilor lui Bob sunt:
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

Observă că semnul negativ al lui 11-|11\rangle este faza globală, deci nu este măsurabil.

5.2 Circuit cuantic care simulează codificarea supradensă

Pe baza protocolului de codificare supradensă, poți construi Circuit-ul de codificare supradensă ca mai jos. Încearcă să schimbi mesajul, msg, pe care Alice vrea să îl transmită lui Bob.

from qiskit import QuantumCircuit

Pașii din Qiskit patterns sunt identificați în comentariile codului.

# 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")

Output of the previous code cell

# 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)

Output of the previous code cell

Poți vedea că Bob a primit mesajul pe care Alice a vrut să i-l trimită.

Acum, hai să încercăm cu un computer cuantic real.

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)

Output of the previous code cell

# 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())

Output of the previous code cell

Rezultatul este cel așteptat. Observă că codificarea supradensă pe un computer cuantic real a arătat mai puține erori decât în cazul teleportării cuantice pe un computer cuantic real. Un motiv pentru aceasta ar putea fi că teleportarea cuantică folosește circuite dinamice, iar codificarea supradensă nu. Vom afla mai multe despre erorile din circuitele cuantice în lecțiile viitoare.

6. Rezumat

În această sesiune, am implementat două protocoale cuantice. Deși scenariile pentru ambele care implică prieteni aflați la distanță sunt oarecum îndepărtate de calculul cuantic pe un singur QPU, ele au aplicații în calculul cuantic și ne ajută să înțelegem mai bine transferul informației cuantice.

  • Teleportare cuantică: Deși nu putem copia stările cuantice, putem teleporta stări cuantice necunoscute prin partajarea entanglament-ului.
  • Codificare cuantică supradensă: O pereche entanglată partajată și transferul unui qubit permit comunicarea a doi biți de informație clasică.
# See the version of Qiskit
import qiskit

qiskit.__version__
'2.0.2'