Kvantne kapije (quantum gates)¶
Kako to možemo da utičemo na kvantna stanja? Videli smo da kvantna stanja definišemo pomoću vektora, dok da bismo menjali te vektore zapravo koristimo matrice.
Naime, promenu kvantnog stanja (u slučaju jednog kjubita to je rotacija na Blohovoj sferi) zapisujemo kao
gde je veličina matrice , pri čemu je za kubite lokalna dimenzija , a broj kubita. U slučaju jednog kjubita , pa je operator zapravo dimenzije .
Među najpoznatijim kvantnim kapijama su zapravo Paulijeve matrice definisane kao
Interesantna stvar je da su vektori svojstveni vektori operatora.
Paulijeve kapije¶
Pogledajmo šta svaka od Paulijevih kapija radi kada deluje na računsku bazu .
Kapija je kvantni NOT (obrtanje bita): ona zamenjuje amplitude uz i ,
Kapija je obrtanje faze (phase flip): ostavlja na miru, a stanju dodaje znak minus,
Kapija istovremeno obrće i bit i fazu (do na imaginarnu jedinicu), :
Sve tri Paulijeve matrice dele nekoliko važnih svojstava. One su istovremeno hermitske () i unitarne (), a pošto su same sebi inverz, kvadrat svake je jedinična matrica,
Dodatno, Paulijeve matrice antikomutiraju i zadovoljavaju ciklične relacije
odakle sledi, na primer, .
Geometrijsko značenje na Blohovoj sferi (klik)
Svaka jednokjubitna kapija odgovara nekoj rotaciji Blohove sfere. Paulijeve kapije su rotacije za ugao oko odgovarajuće koordinatne ose:
— rotacija za oko -ose,
— rotacija za oko -ose,
— rotacija za oko -ose.
Na primer, obrne stanje (na pozitivnoj -osi) u (na negativnoj -osi).

Slika 1:Prethodna vizuelizacija ponovo iskrošćena.
Hadamardova kapija¶
Najvažnija kapija koja pravi superpoziciju iz stanja računske baze je Hadamardova kapija
Njeno dejstvo na bazna stanja daje upravo stanja i sa Blohovog ekvatora (vidi tabelu specijalnih stanja u ):
Hadamardova kapija je i hermitska i unitarna, pa je sama sebi inverz, .
Fazne kapije: i ¶
Pored , često nam trebaju „blaže" rotacije faze, koje stanju dodaju fazu manju od . Uopšteno, fazna kapija deluje kao
Tri posebna slučaja imaju svoja imena:
Kapija je „kvadratni koren" iz , a je koren iz :
--> Za razliku od Paulijevih kapija i Hadamarda, kapije i nisu same sebi inverz (, ); one su prve u nizu kapija koje ćemo koristiti da bismo dosegli proizvoljno stanje na sferi.
Rotacione kapije¶
Najprirodniji način da napravimo rotaciju za proizvoljan ugao je da eksponenciramo Paulijevu matricu. Za definišemo rotacionu kapiju
Pošto je (iz (7)), razvoj eksponencijalne funkcije se „lomi" na paran i neparan deo i sažima u zatvorenu formu
što je operatorska verzija Ojlerove formule.
Prikaži izvođenje (klik)
Krenimo od definicije eksponencijalne funkcije operatora preko stepenog (Tejlorovog) reda:
Ključno svojstvo je (iz (7)): stepeni operatora smenjuju se u samo dve vrednosti,
Zato red razdvajamo na parne () i neparne () članove — parni skupljaju , a neparni :
Pošto je , sledi i , pa se dva koeficijenta svode na poznate Tejlorove redove kosinusa i sinusa (argumenta ):
Uvrštavanjem nazad dobijamo zatvorenu formu
što je upravo (15). Izvođenje počiva jedino na , pa važi jednoobrazno za i odmah daje matrice iz (21).
Uvrštavanjem dobijamo tri standardne rotacione kapije
Veza sa Paulijevim kapijama (klik)
Opšta parametrizovana kapija ¶
Sve prethodne kapije su specijalni slučajevi jedne opšte jednokubitne kapije. U Qiskit okruženju najopštija jednokjubitna kapija se definiše (do na nebitnu globalnu fazu) sa tri realna ugla kao
Broj parametara se lepo slaže sa geometrijom: matrica (specijalna unitarna grupa) ima tačno tri realna slobodna parametra, a zapravo nije ništa drugo do Ojlerova dekompozicija na tri rotacije, (do na globalnu fazu).
Sada je lako proveriti da su sve dosadašnje kapije samo posebni izbori uglova. Paulijeve matrice se dobijaju kao
dok se rotacione kapije zapisuju kao
Kapije su predstavljene u sledećoj tabeli.
| Kapija | Matrica | Kao |
|---|---|---|
Vaš kvantni kod: kapije u Python-u¶
Kao i u prošloj lekciji, sve možemo direktno da proverimo u nekoliko linija koda. Prvo definišemo Paulijeve matrice i osnovne kapije.
import numpy as np
# Računska baza |0> i |1> (vektori kolone)
ket0 = np.array([[1], [0]], dtype=complex)
ket1 = np.array([[0], [1]], dtype=complex)
# --- Paulijeve matrice i osnovne kapije ---
I2 = np.eye(2, dtype=complex)
X = np.array([[0, 1], [1, 0]], dtype=complex)
Y = np.array([[0, -1j], [1j, 0]], dtype=complex)
Z = np.array([[1, 0], [0, -1]], dtype=complex)
H = (1/np.sqrt(2)) * np.array([[1, 1], [1, -1]], dtype=complex)
S = np.array([[1, 0], [0, 1j]], dtype=complex)
T = np.array([[1, 0], [0, np.exp(1j*np.pi/4)]], dtype=complex)
# dejstvo kapija na baznim stanjima
print("X|0> =\n", X @ ket0) # -> |1>
print("Z|1> =\n", Z @ ket1) # -> -|1>
print("H|0> =\n", H @ ket0) # -> |+>Proverimo ključna algebarska svojstva iz lekcije — unitarnost, involutivnost i to da su i koreni iz :
# unitarnost: U^dagger U = I (npr. za Hadamard)
print("H unitarno? ", np.allclose(H.conj().T @ H, I2))
# involutivnost Paulijevih kapija i Hadamarda: P^2 = I
print("X^2 = I? ", np.allclose(X @ X, I2))
print("H^2 = I? ", np.allclose(H @ H, I2))
# koreni: S^2 = Z i T^2 = S
print("S^2 = Z? ", np.allclose(S @ S, Z))
print("T^2 = S? ", np.allclose(T @ T, S))
# Hadamard kao (X + Z)/sqrt(2)
print("H = (X+Z)/sqrt(2)? ", np.allclose(H, (X + Z)/np.sqrt(2)))Rotacione kapije i opštu kapiju najlakše je zapisati kao funkcije uglova:
def Rx(theta):
return np.array([[np.cos(theta/2), -1j*np.sin(theta/2)],
[-1j*np.sin(theta/2), np.cos(theta/2)]], dtype=complex)
def Ry(theta):
return np.array([[np.cos(theta/2), -np.sin(theta/2)],
[np.sin(theta/2), np.cos(theta/2)]], dtype=complex)
def Rz(theta):
return np.array([[np.exp(-1j*theta/2), 0],
[0, np.exp(1j*theta/2)]], dtype=complex)
def U(theta, phi, lam):
return np.array([
[np.cos(theta/2), -np.exp(1j*lam)*np.sin(theta/2)],
[np.exp(1j*phi)*np.sin(theta/2), np.exp(1j*(phi+lam))*np.cos(theta/2)]
], dtype=complex)
# svaka poznata kapija je specijalan slučaj opšte U(theta, phi, lam):
print("X = U(pi,0,pi)? ", np.allclose(X, U(np.pi, 0, np.pi)))
print("Y = U(pi,pi/2,pi/2)? ", np.allclose(Y, U(np.pi, np.pi/2, np.pi/2)))
print("Z = U(0,0,pi)? ", np.allclose(Z, U(0, 0, np.pi)))
print("H = U(pi/2,0,pi)? ", np.allclose(H, U(np.pi/2, 0, np.pi)))
print("S = U(0,0,pi/2)? ", np.allclose(S, U(0, 0, np.pi/2)))
print("T = U(0,0,pi/4)? ", np.allclose(T, U(0, 0, np.pi/4)))
print("Rx = U(t,-pi/2,pi/2)? ", np.allclose(Rx(0.7), U(0.7, -np.pi/2, np.pi/2)))
print("Ry = U(t,0,0)? ", np.allclose(Ry(0.7), U(0.7, 0, 0)))
print("Rz = e^{-it/2}U(0,0,t)?", np.allclose(Rz(0.7), np.exp(-1j*0.7/2)*U(0, 0, 0.7)))Vizuelizacija dejstva kapija na Blohovoj sferi¶
Pošto svaka jednokjubitna kapija odgovara rotaciji Blohove sfere, najbolji način da je „osetimo" jeste da nacrtamo stanje pre i posle dejstva kapije. Prvo nam treba funkcija koja iz vektora stanja računa Blohov vektor :
def bloch_vector(psi):
"""Blohov vektor r = (<X>, <Y>, <Z>) za stanje jednog kjubita."""
psi = psi.reshape(2, 1)
rx = (psi.conj().T @ X @ psi).item().real
ry = (psi.conj().T @ Y @ psi).item().real
rz = (psi.conj().T @ Z @ psi).item().real
return np.array([rx, ry, rz])
# provera: |0> je na severnom polu (0,0,1), |+> na +x osi (1,0,0)
print("r(|0>) =", np.round(bloch_vector(ket0), 3)) # [0 0 1]
print("r(H|0>) =", np.round(bloch_vector(H @ ket0), 3)) # [1 0 0] -> |+>Sledeći blok crta providnu sferu sa koordinatnim osama (pomoćna funkcija), a zatim iscrtava stanje pre (ljubičasto) i posle (narandžasto) delovanja izabrane kapije:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # 3D projekcija
%matplotlib inline
def nacrtaj_sferu(ax):
# providna sferična mreža
u = np.linspace(0, 2*np.pi, 60)
v = np.linspace(0, np.pi, 60)
xs = np.outer(np.cos(u), np.sin(v))
ys = np.outer(np.sin(u), np.sin(v))
zs = np.outer(np.ones_like(u), np.cos(v))
ax.plot_surface(xs, ys, zs, color="black", alpha=0.06,
linewidth=0, rstride=2, cstride=2, antialiased=True, shade=False)
# ekvator
circ = np.linspace(0, 2*np.pi, 200)
ax.plot(np.cos(circ), np.sin(circ), 0, color="#555555", lw=0.8, alpha=0.5)
# tri ose (oba smera)
for d, col in [((1,0,0), "#c0392b"), ((0,1,0), "#27ae60"), ((0,0,1), "#34495e")]:
dx, dy, dz = d
ax.quiver(0,0,0, 1.3*dx, 1.3*dy, 1.3*dz, color=col, lw=1.2, arrow_length_ratio=0.05)
ax.quiver(0,0,0, -1.3*dx, -1.3*dy, -1.3*dz, color=col, lw=1.2, arrow_length_ratio=0.05)
ax.text(1.45, 0, 0, r"$x$", color="#c0392b")
ax.text(0, 1.42, 0, r"$y$", color="#27ae60")
ax.text(0, 0, 1.45, r"$z$", color="#34495e")
ax.set_box_aspect([1,1,1])
ax.set_xlim(-1.1,1.1); ax.set_ylim(-1.1,1.1); ax.set_zlim(-1.1,1.1)
ax.set_axis_off()
# --- IZABERI kapiju i početno stanje ---
kapija = H # probaj i X, Z, S, T, Rx(np.pi/2), Ry(np.pi/3) ...
psi_pre = ket0 # početno stanje
psi_posle = kapija @ psi_pre # stanje posle dejstva kapije
r_pre = bloch_vector(psi_pre)
r_posle = bloch_vector(psi_posle)
fig = plt.figure(figsize=(7, 7))
ax = fig.add_subplot(111, projection="3d")
nacrtaj_sferu(ax)
ax.quiver(0,0,0, *r_pre, color="#8e44ad", lw=3, arrow_length_ratio=0.12)
ax.text(*(1.15*r_pre), r"pre", color="#8e44ad", fontsize=13)
ax.quiver(0,0,0, *r_posle, color="#e67e22", lw=3, arrow_length_ratio=0.12)
ax.text(*(1.15*r_posle), r"posle", color="#e67e22", fontsize=13)
ax.set_title("Dejstvo kapije na Blohovoj sferi", fontsize=13, pad=8)
ax.view_init(elev=18, azim=35)
plt.tight_layout()
plt.savefig("dejstvo_kapije.png", dpi=300, bbox_inches="tight")
plt.show()Menjajući promenljivu kapija (na primer u X, Z, S, T, Rx(np.pi/2), Ry(np.pi/3)) i početno stanje psi_pre, možeš da vidiš kako svaka kapija rotira Blohov vektor: Paulijeve i Hadamardova za ugao , a rotacione za proizvoljan ugao koji sam biraš.
Univerzalnost: , i ¶
Prirodno pitanje je: koliko kapija nam zaista treba da bismo mogli da izvedemo bilo koje kvantno računanje? Neće nam trebati beskonačna riznica kapija — dovoljan je mali, konačan skup.
Za jedan kjubit, opšta kapija pokriva sve rotacije, ali na pravom hardveru ne možemo da podesimo uglove savršeno precizno. Zato tražimo konačan (diskretan) skup kapija čijim kombinovanjem možemo da se proizvoljno blizu približimo svakoj željenoj kapiji. Ključne su dve grupe:
Klifordove kapije (i za više kjubita) — generišu takozvanu Klifordovu grupu. One su moćne, ali ih klasičan računar može efikasno simulirati (Gotesman–Nilova teorema Gottesman, 1998; vidi i Nielsen & Chuang, 2010, odeljak 10.5.4), pa same po sebi ne daju kvantnu prednost.
kapija — dodavanje jedne jedine ne-Klifordove kapije skupu daje skup (odnosno za jedan kjubit) koji je univerzalan: njime se svaka jednokjubitna kapija može aproksimirati do proizvoljne tačnosti.
Da ta aproksimacija bude i efikasna, garantuje Solovej–Kitajeva teorema: svaku željenu jednokjubitnu kapiju možemo aproksimirati sa greškom koristeći samo kapija iz skupa (uz malu konstantu ). Drugim rečima, cena veće preciznosti raste tek poli-logaritamski, što je izuzetno povoljno.
Vežbe¶
Rešenje
Množenjem matrice i vektora dobijamo i slično . Kapija zamenjuje ulogu stanja i , baš kao klasična NOT operacija nad bitom.
print("X|0> =\n", X @ ket0) # |1>
print("X|1> =\n", X @ ket1) # |0>Rešenje
. Na Blohovoj sferi je rotacija za oko -ose; ona šalje , pa tačku (na ) prebacuje u (na ).
plus = (ket0 + ket1)/np.sqrt(2)
minus = (ket0 - ket1)/np.sqrt(2)
print("Z|+> = |-> ? ", np.allclose(Z @ plus, minus))Rešenje
Za Hadamard: . Za faznu kapiju: , i analogno .
print("H^2 = I? ", np.allclose(H @ H, I2))
print("S^2 = Z? ", np.allclose(S @ S, Z))
print("T^2 = S? ", np.allclose(T @ T, S))Rešenje
. Slično je , pa je — Paulijeve matrice ne komutiraju (zapravo antikomutiraju, ).
print("XY = iZ? ", np.allclose(X @ Y, 1j*Z))
print("YX = -iZ? ", np.allclose(Y @ X, -1j*Z))Rešenje
Za je . Uz , dobijamo jer je .
print("H = U(pi/2, 0, pi)? ", np.allclose(H, U(np.pi/2, 0, np.pi)))Jovan Odavić · dzovan90 [at] gmail [dot] com · www.jovanodavic.com
- Gottesman, D. (1998). The Heisenberg Representation of Quantum Computers. arXiv Preprint arXiv:Quant-Ph/9807006. 10.48550/arXiv.quant-ph/9807006
- Nielsen, M. A., & Chuang, I. L. (2010). Quantum Computation and Quantum Information: 10th Anniversary Edition. Cambridge University Press. 10.1017/CBO9780511976667