Algoritmul lui Deutsch
Algoritmul lui Deutsch rezolvă problema parității pentru cazul special în care În contextul calculului cuantic, această problemă este uneori denumită problema lui Deutsch, iar în această lecție vom folosi această nomenclatură.
Mai precis, intrarea este reprezentată printr-o funcție de la un bit la un bit. Există patru astfel de funcții:
Prima și ultima dintre aceste funcții sunt constante, iar celelalte două din mijloc sunt echilibrate, adică cele două valori posibile de ieșire ale funcției apar de același număr de ori pe măsură ce parcurgem toate intrările. Problema lui Deutsch constă în a determina căreia dintre aceste două categorii îi aparține funcția de intrare: constantă sau echilibrată.
Dacă privim funcția de intrare din problema lui Deutsch ca pe un acces aleator la un șir de caractere, ne gândim la un șir de doi biți:
Privind astfel, problema lui Deutsch constă în calcularea parității (sau, echivalent, a SAU-EXCLUSIV) celor doi biți.
Orice algoritm clasic de interogare care rezolvă corect această problemă trebuie să interogheze ambii biți: și Dacă aflăm, de exemplu, că răspunsul poate fi în continuare sau în funcție de dacă sau respectiv. Fiecare alt caz este similar; cunoașterea a doar unui singur bit din doi nu oferă nicio informație despre paritatea lor. Prin urmare, circuitul boolean descris în secțiunea anterioară este cel mai bun rezultat posibil din punctul de vedere al numărului de interogări necesare pentru a rezolva această problemă.
Descrierea circuitului cuantic
Algoritmul lui Deutsch rezolvă problema lui Deutsch folosind o singură interogare, oferind astfel un avantaj cuantificabil al calculului cuantic față de cel clasic. Acesta poate părea un avantaj modest — o interogare față de două — dar trebuie să începem de undeva. Progresele științifice au uneori origini aparent modeste.
Iată un circuit cuantic care descrie algoritmul lui Deutsch:
Analiză
Pentru a analiza algoritmul lui Deutsch, vom parcurge acțiunea circuitului de mai sus și vom identifica stările qubiților la momentele sugerate de această figură:
Starea inițială este iar cele două operații Hadamard din partea stângă a circuitului transformă această stare în
(Ca întotdeauna, urmăm convenția de ordonare a qubiților din Qiskit, care plasează qubit-ul de sus la dreapta și qubit-ul de jos la stânga.) Poate părea neintuitivă scrierea acestei stări produs parțial distribuită (lăsând stările qubit-ului 1 factorizate), dar acest lucru va face expresiile ulterioare mai compacte.
În continuare, se aplică poarta . Conform definiției porții , valoarea funcției pentru starea clasică a qubit-ului din dreapta/sus este aplicată prin XOR pe qubit-ul din stânga/jos, transformând în starea
Putem simplifica această expresie observând că formula
este valabilă pentru ambele valori posibile Mai explicit, cele două cazuri sunt următoarele.
Astfel, putem exprima alternativ în felul următor:
Tocmai s-a întâmplat ceva interesant! Deși acțiunea porții asupra stărilor din baza standard lasă qubit-ul din dreapta/sus neschimbat și aplică XOR cu valoarea funcției pe qubit-ul din stânga/jos, vedem că starea qubit-ului din dreapta/sus s-a schimbat (în general), în timp ce starea qubit-ului din stânga/jos rămâne aceeași — aflându-se în starea atât înainte, cât și după aplicarea porții . Acest fenomen este cunoscut sub numele de phase kickback și vom vorbi mai mult despre el în curând.
Cu o ultimă simplificare, și anume extragerea factorului în afara sumei, obținem această expresie a stării :
Observă că în această expresie avem în exponentul lui în loc de ceea ce ne-am putea aștepta dintr-un punct de vedere pur algebric, dar obținem același rezultat în ambele cazuri. Aceasta deoarece valoarea pentru orice număr întreg depinde doar de dacă este par sau impar.
Aplicând ultima poartă Hadamard qubit-ului de sus, obținem starea
care conduce la rezultatul corect cu probabilitatea atunci când qubit-ul din dreapta/sus este măsurat.
Observații suplimentare despre phase kickback
Înainte de a continua, să privim analiza de mai sus dintr-un unghi ușor diferit, care poate clarifica fenomenul de phase kickback.
În primul rând, observă că formula de mai jos este valabilă pentru orice alegere de biți
Aceasta poate fi verificată pentru cele două valori posibile și :
Folosind această formulă, vedem că
pentru orice alegere de biți Deoarece această formulă este adevărată pentru și vedem prin liniaritate că
pentru orice vector de stare qubit și prin urmare
Cheia care face ca asta să funcționeze este că În termeni matematici, vectorul este un vector propriu al matricei cu valoarea proprie
Vom discuta vectorii proprii și valorile proprii în mai mare detaliu în lecția viitoare despre estimarea fazei și factorizare, unde fenomenul de phase kickback este generalizat la alte operații unitare.
Ținând cont că scalarele se propagă liber prin produse tensoriale, găsim o modalitate alternativă de a explica cum operația transformă în în analiza de mai sus:
Implementare în Qiskit
Acum să vedem cum putem implementa algoritmul lui Deutsch în Qiskit. Vom începe cu o verificare a versiunii și apoi vom efectua importurile necesare exclusiv pentru această implementare. Pentru implementările altor algoritmi care urmează, vom efectua importurile necesare separat, pentru o modularitate mai mare.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit import __version__
print(__version__)
2.1.1
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
Mai întâi vom defini un Circuit cuantic care implementează un query gate pentru una dintre cele patru funcții sau de la un bit la un bit, descrise anterior. Cum am menționat deja, implementarea query gate-urilor nu face cu adevărat parte din algoritmul lui Deutsch în sine; aici arătăm practic o modalitate de a pregăti intrarea, sub forma unei implementări cu circuit a unui query gate.
def deutsch_function(case: int):
# This function generates a quantum circuit for one of the 4 functions
# from one bit to one bit
if case not in [1, 2, 3, 4]:
raise ValueError("`case` must be 1, 2, 3, or 4.")
f = QuantumCircuit(2)
if case in [2, 3]:
f.cx(0, 1)
if case in [3, 4]:
f.x(1)
return f
Putem vedea cum arată fiecare circuit folosind metoda draw. Iată circuitul pentru funcția
display(deutsch_function(3).draw(output="mpl"))
În continuare vom crea circuitul cuantic propriu-zis pentru algoritmul lui Deutsch, înlocuind query gate-ul cu o implementare de circuit cuantic furnizată ca argument. În scurt timp vom introduce unul dintre cele patru circuite definite de funcția deutsch_function pe care am definit-o anterior.
Barierele sunt incluse pentru a arăta separarea vizuală dintre implementarea query gate-ului și restul circuitului.
def compile_circuit(function: QuantumCircuit):
# Compiles a circuit for use in Deutsch's algorithm.
n = function.num_qubits - 1
qc = QuantumCircuit(n + 1, n)
qc.x(n)
qc.h(range(n + 1))
qc.barrier()
qc.compose(function, inplace=True)
qc.barrier()
qc.h(range(n))
qc.measure(range(n), range(n))
return qc
Din nou, putem vedea cum arată circuitul folosind metoda draw.
display(compile_circuit(deutsch_function(3)).draw(output="mpl"))
În final, vom crea o funcție care rulează circuitul definit anterior o singură dată și afișează rezultatul corespunzător: „constant" sau „balanced."
def deutsch_algorithm(function: QuantumCircuit):
# Determine if a one-bit function is constant or balanced.
qc = compile_circuit(function)
result = AerSimulator().run(qc, shots=1, memory=True).result()
measurements = result.get_memory()
if measurements[0] == "0":
return "constant"
return "balanced"
Putem rula acum algoritmul lui Deutsch pe oricare dintre cele patru funcții definite mai sus.
f = deutsch_function(3)
display(deutsch_algorithm(f))
'balanced'