Deutschův algoritmus
Deutschův algoritmus řeší problém parity pro speciální případ, kdy V kontextu kvantového počítání se tento problém někdy označuje jako Deutschův problém a v této lekci se budeme držet tohoto pojmenování.
Přesněji řečeno, vstup je reprezentován funkcí z jednoho bitu na jeden bit. Takové funkce existují čtyři:
První a poslední z těchto funkcí jsou konstantní a prostřední dvě jsou vyvážené (balanced), což znamená, že obě možné výstupní hodnoty funkce se vyskytují stejně často, když procházíme všechny vstupy. Deutschův problém spočívá v určení, do které z těchto dvou kategorií vstupní funkce patří: konstantní nebo vyvážená.
Pokud se na vstupní funkci v Deutschově problému díváš jako na reprezentaci náhodného přístupu k řetězci, mluvíme o dvoubitovém řetězci:
Při tomto pohledu Deutschův problém spočívá ve výpočtu parity (nebo ekvivalentně exkluzivního OR) těchto dvou bitů.
Každý klasický dotazovací algoritmus, který správně řeší tento problém, se musí dotázat na oba bity: a Pokud se například dozvíme, že odpověď může být stále nebo v závislosti na tom, zda nebo Každý další případ je obdobný; znalost pouze jednoho ze dvou bitů neposkytuje vůbec žádnou informaci o jejich paritě. Booleovský Circuit popsaný v předchozí části je tedy to nejlepší, čeho můžeme dosáhnout z hlediska počtu dotazů potřebných k vyřešení tohoto problému.
Popis kvantového Circuit
Deutschův algoritmus řeší Deutschův problém pomocí jediného dotazu, a poskytuje tak kvantifikovatelnou výhodu kvantového výpočtu oproti klasickému. Může to být skromná výhoda — jeden dotaz oproti dvěma — ale někde začít musíme. Vědecký pokrok má někdy zdánlivě skromné počátky.
Zde je kvantový Circuit, který popisuje Deutschův algoritmus:
Analýza
Pro analýzu Deutschova algoritmu projdeme působení výše uvedeného Circuit a identifikujeme stavy Qubit v časech naznačených tímto obrázkem:
Počáteční stav je a dvě Hadamardovy operace na levé straně Circuit transformují tento stav na
(Jak vždy, dodržujeme konvenci řazení Qubit v Qiskitu, která umísťuje horní Qubit doprava a dolní Qubit doleva.) Může se zdát neintuitivní zapsat tento produktový stav částečně rozepsaný (ponechat stavy Qubit 1 vytažené před závorku), ale díky tomu budou naše pozdější výrazy kompaktnější.
Dále se provede Gate Podle definice Gate se hodnota funkce pro klasický stav horního/pravého Qubit XORuje na dolní/levý Qubit, čímž se transformuje do stavu
Tento výraz můžeme zjednodušit pozorováním, že vzorec
funguje pro obě možné hodnoty Explicitněji, oba případy vypadají následovně. Konkrétněji, tyto dva případy vypadají následovně.
Takže můžeme alternativně vyjádřit takto:
Právě se stalo něco zajímavého! Ačkoli působení Gate na standardní bázové stavy ponechává horní/nejpravější Qubit beze změny a XORuje hodnotu funkce na spodní/nejlevější Qubit, zde vidíme, že se stav horního/nejpravějšího Qubitu (obecně) změnil, zatímco stav spodního/nejlevějšího Qubitu zůstal stejný — konkrétně ve stavu před i po provedení Gate . Tento jev je známý jako phase kickback (fázový zpětný ráz) a za chvíli si o něm řekneme víc.
S jedním posledním zjednodušením, kterým je vytažení faktoru před součet, získáme tento výraz stavu :
Všimni si, že v tomto výrazu máme v exponentu místo což bychom mohli očekávat z čistě algebraického hlediska, ale výsledek je v obou případech stejný. Je to proto, že hodnota pro libovolné celé číslo závisí pouze na tom, zda je sudé nebo liché.
Aplikací poslední Hadamardovy Gate na horní Qubit získáme stav
což vede ke správnému výsledku s pravděpodobností při měření pravého/horního Qubitu.
Další poznámky k phase kickbacku
Než budeme pokračovat, podívejme se na výše uvedenou analýzu z mírně odlišného úhlu, který může osvětlit jev phase kickbacku.
Nejprve si všimni, že následující vzorec platí pro všechny volby bitů
To lze ověřit kontrolou pro dvě možné hodnoty a :
Pomocí tohoto vzorce vidíme, že
pro každou volbu bitů Protože tento vzorec platí pro a z linearity vyplývá, že
pro všechny stavové vektory Qubitu a proto
Klíčem, díky kterému to funguje, je to, že V matematické terminologii je vektor vlastním vektorem matice s vlastním číslem
Vlastní vektory a vlastní čísla probereme podrobněji v nadcházející lekci o odhadu fáze a faktorizaci, kde je jev phase kickbacku zobecněn na další unitární operace.
S vědomím, že skaláry volně procházejí tenzorovými součiny, najdeme alternativní způsob uvažování o tom, jak operace transformuje na ve výše uvedené analýze:
Implementace v Qiskit
Teď se podíváme, jak můžeš implementovat Deutschův algoritmus v Qiskit. Začneme kontrolou verze a poté provedeme importy potřebné výhradně pro tuto implementaci. Pro implementace dalších algoritmů, které následují, provedeme potřebné importy zvlášť kvůli větší modularitě.
# 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
Nejprve definujeme kvantový Circuit, který implementuje query Gate pro jednu ze čtyř funkcí nebo z jednoho bitu do jednoho bitu, popsaných dříve. Jak jsme již zmínili, implementace query Gate není ve skutečnosti součástí samotného Deutschova algoritmu; zde v podstatě ukazujeme jeden způsob, jak připravit vstup ve formě implementace query Gate jako Circuit.
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
Pomocí metody draw si můžeš prohlédnout, jak každý Circuit vypadá. Tady je Circuit pro funkci
display(deutsch_function(3).draw(output="mpl"))
Dále vytvoříme samotný kvantový Circuit pro Deutschův algoritmus, přičemž query Gate nahradíme implementací kvantového Circuit zadanou jako argument. Za chvíli do něj zapojíme jeden ze čtyř Circuit definovaných funkcí deutsch_function, kterou jsme definovali dříve.
Bariéry jsou zahrnuty pro vizuální oddělení implementace query Gate od zbytku Circuit.
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
Opět si můžeš prohlédnout, jak Circuit vypadá, pomocí metody draw.
display(compile_circuit(deutsch_function(3)).draw(output="mpl"))
Nakonec vytvoříme funkci, která spustí dříve definovaný Circuit jednou a vypíše odpovídající výsledek: „constant" nebo „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"
Teď můžeš spustit Deutschův algoritmus na kteroukoli ze čtyř výše definovaných funkcí.
f = deutsch_function(3)
display(deutsch_algorithm(f))
'balanced'