Kvantna kola (quantum circuits)¶
U prošloj lekciji upoznali smo pojedinačne kvantne kapije kao matrice . Sada ćemo videti kako se one nižu jedna za drugom u kvantno kolo: dijagram koji se čita kao note, s leva na desno, kroz vreme.

Slika 1:Tri koraka svake muzičke kompozicije. Violinski ključ (početak kompozicije), note (sama kompozicija), i kraj (znak za kraj kompozicije).
Kvantno kolo je zapravo „recept" za ceo kvantni proračun: kako da pripremimo, transformišemo i izmerimo kubit.
Tri koraka svakog kvantnog procesa¶
Svaki kvantno-mehanički proces (pa i svaki kvantni proračun) sastoji se iz tri koraka:
priprema kvantnog stanja, gde obično krećemo iz ,
evolucija stanja delovanjem kapija, tj. iz (1),
merenje stanja koje daje klasičan bit (Bornovom pravilo prikazano u sledećoj lekciji Kvantno merenje).

Slika 2:Tri koraka svakog kvantnog procesa na primeru jednog kubita: priprema ( na severnom polu Blohove sfere), evolucija (kapija zarotira stanje) i merenje (instrument daje klasičan bit 0 ili 1).
Cilj ove lekcije je da naučimo da čitamo i pišemo ovakve dijagrame, i da ih povežemo sa matricama iz prethodne lekcije.
Ovakav tip diskretne kvantne mehanika deli sličnost sa muzičkim notama kao što smo već videli.
Ne treba zaboraviti da najčešće sa merenjem asociramo osu z! (slučaj superprovodnih kubita)
Šta je kvantno kolo?¶
Kvantno kolo je dijagram sa nekoliko jednostavnih pravila:
žica (horizontalna linija) predstavlja jedan kubit; vreme teče s leva na desno,
kubit počinje u stanju na levom kraju,
kapije su kutije (ili simboli) na žici; kad stanje „prođe" kroz kutiju , ono se transformiše u ,
na kraju je merni instrument (simbol „merača"), koji stanje pretvara u klasičan bit. Klasičan bit vodimo dvostrukom linijom da bismo ga razlikovali od kvantne žice.

Slika 3:Tehnički crtež napravljen pomoću Qiskit paketa jednokubitno kolo: kubit krene iz , prođe kroz kapije i , pa se meri; rezultat (klasičan bit) upisuje se u klasični registar (dvostruka linija).
Kasnije ćemo videti i kola sa više žica (više kubita, jedna iznad druge); zasad ostajemo na jednom kubitu.
Kolo je proizvod matrica (redosled je obrnut!)¶
Neka kolo prvo primeni kapiju , pa , pa na početno stanje . To kolo možemo dijagramatički da predstavimo na sledeći način:

Slika 4:Primer kola sa više kapija. Imati na umu da ovo nije kompletna vizuelizacija, već samo delimična sa stanjima na početku i na kraju. Tehnički diagram ne nužno imaju takav zapis.
Pošto svaka naredna kapija deluje na rezultat prethodne, ukupno dejstvo je
Uočite obrnut redosled: iako u kolu prvo crtamo , u proizvodu matrica ona stoji skroz desno (jer prva deluje na stanje).
Prethodni primer¶
Pogledajmo konkretan primer sa Slika 3: kolo (prvo , pa ). Njegova matrica je (a ne !):
Prikaži računicu (klik)
Prvo deluje : . Zatim deluje :
Dobili smo tačno magično stanje iz Kvantne kapije! Da smo greškom pomnožili (pogrešan redosled), dobili bismo drugačije stanje. Ko je to stanje?
Isto možemo da proverimo na dva načina — „ručno" preko matrica (kao u prošloj lekciji) i preko Qiskit kola.
import numpy as np
# matrice kapija (iste kao u prošloj lekciji)
I2 = np.eye(2, dtype=complex)
X = np.array([[0, 1], [1, 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)
ket0 = np.array([[1], [0]], dtype=complex)
def Rz(theta):
return np.array([[np.exp(-1j*theta/2), 0],
[0, np.exp(1j*theta/2)]], dtype=complex)Prvo „ručno", matricama — pazimo na obrnut redosled:
# Kolo |0> --H--T-- ; redosled matrica je OBRNUT od crtanja:
U_kolo = T @ H # prvo H, pa T -> T·H
psi = U_kolo @ ket0
print("Izlazno stanje =\n", np.round(psi, 3)) # (|0> + e^{i pi/4}|1>)/sqrt(2) = |T>Hajde da obavimo isti račun koristeći QisKit. Gde je prvo potrebno instalirati paket pomoću komande
# instalacije QisKit-a i dodatka zabolju vizuelizaciju
!pip install qiskit
!pip install pylatexencA sada isto to kao Qiskit kolo. QuantumCircuit sam množi matrice u obrnutom redosledu umesto nas:
# učitati potrebne funkcije iz QisKit paketa
from qiskit import QuantumCircuit
# definisati kvantno kolo
qc = QuantumCircuit(1)
qc.h(0) # prvo nacrtamo (i primenimo) H
qc.t(0) # pa T# provera da se Qiskit slaže sa T·H (a ne H·T):
print("Qiskit = T·H ? ", np.allclose(Operator(qc).data, T @ H))
print("Stanje:", np.round(Statevector(qc).data, 3))Vizuelizacija kola iz Slika 3.
qc.measure_all()
qc.draw('mpl', style='iqp')
U slučaju greške pri izvršenju (klik)
U slučaju greške pri puštanju koda, potrebno je restart-ovati ‘Runtime session’ vašeg Jupiter notebook-a.
Priprema proizvoljnog stanja kolom¶
Kolo nam služi i da iz napravimo bilo koje željeno stanje. Iz prošle lekcije znamo da opšta kapija iz (23) pokriva sve rotacije, pa jedno kolo može da dosegne svaku tačku Blohove sfere.
Za tačke na ekvatoru dovoljni su i jedna : prvo (dovede nas na ekvator, u ), pa (zavrti za azimut ).
# Kolo |0> --H--Rz(phi)-- priprema stanje na ekvatoru sa azimutom phi:
phi = np.radians(70)
psi = Rz(phi) @ H @ ket0 # matrica kola je Rz·H (obrnut redosled!)
azimut = np.degrees(np.angle(psi[1, 0] / psi[0, 0]))
print("Blohov azimut stanja:", round(azimut, 1), "stepeni") # ~ 70# isto kolo u Qiskit-u:
qc = QuantumCircuit(1)
qc.h(0)
qc.rz(np.radians(70), 0)
qc.measure_all()
qc.draw('mpl', style='iqp')Merenje: kraj kola¶
Na kraju kola merimo kjubit u računskoj bazi . Po Bornovom pravilu iz , verovatnoće ishoda su i , pa jedno merenje daje jedan klasičan bit. U kolu ga zapisujemo sa qc.measure_all(), kao na Slika 3.
Time je „recept" kola potpun: pripremi, evoluiraj, izmeri. Kako iz pojedinačnih merenja dobijamo verovatnoće i celo stanje, kako merimo u drugim bazama, i kako se kolo pokreće na pravom kvantnom računaru je tema naredne lekcije, Kvantno merenje.
Vežbe¶
Rešenje
Redosled crtanja je , pa je matrica kola (prvo nacrtano stoji skroz desno). Direktnim množenjem se dobija , pa . Kolo je, dakle, samo „preobučeni" kvantni NOT.
print("H·Z·H = X ? ", np.allclose(H @ Z @ H, X))
# Kit provera preko matrice kola:
qc = QuantumCircuit(1); qc.h(0); qc.z(0); qc.h(0)
print("Operator(qc) = X ? ", np.allclose(Operator(qc).data, X))Rešenje
Najkraće je , tj. kolo sa matricom . (Podjednako radi i , jer .)
ket1 = np.array([[0], [1]], dtype=complex)
minus = (ket0 - ket1)/np.sqrt(2)
print("Kolo Z·H daje |-> ? ", np.allclose(Z @ H @ ket0, minus))
# Qiskit:
qc = QuantumCircuit(1); qc.h(0); qc.z(0)
print("Stanje:", np.round(Statevector(qc).data, 3)) # (1, -1)/sqrt(2) = |->Jovan Odavić · dzovan90 [at] gmail [dot] com · www.jovanodavic.com