Transformata Fourier cuantică
Pentru acest modul Qiskit in Classrooms, studenții trebuie să aibă un mediu Python funcțional cu următoarele pachete instalate:
qiskitv2.1.0 sau mai nouqiskit-ibm-runtimev0.40.1 sau mai nouqiskit-aerv0.17.0 sau mai nouqiskit.visualizationnumpypylatexenc
Pentru a configura și instala pachetele de mai sus, consultă ghidul Instalare Qiskit. Pentru a rula joburi pe computere cuantice reale, studenții vor trebui să își creeze un cont IBM Quantum® urmând pașii din ghidul Configurează-ți contul IBM Cloud.
Acest modul a fost testat și a folosit 13 secunde de timp QPU. Aceasta este o estimare de bună-credință; utilizarea ta reală poate varia.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'
Introducere
Transformata Fourier este un instrument omniprezent cu aplicații în matematică, fizică, procesarea semnalelor, compresia datelor și nenumărate alte domenii. O versiune cuantică a transformatei Fourier, numită pe bună dreptate transformata Fourier cuantică, stă la baza unora dintre cei mai importanți algoritmi cuantici.
Astăzi, după o reîmprospătare a transformatei Fourier clasice, vom vorbi despre cum implementăm transformata Fourier cuantică pe un computer cuantic. Apoi, vom discuta una dintre aplicațiile transformatei Fourier cuantice într-un algoritm numit algoritmul de estimare a fazei. Estimarea cuantică a fazei este o subrutină în celebrul algoritm de factorizare al lui Shor, uneori denumit „bijuteria de coroană" a calculului cuantic. Acest modul se îndreaptă spre un alt modul dedicat în întregime algoritmului lui Shor, dar este conceput și ca unul de sine stătător. Transformata Fourier cuantică este un algoritm fascinant și util în sine!
Transformata Fourier clasică
Înainte să ne aruncăm în transformata Fourier cuantică, să ne reîmprospătăm mai întâi cunoștințele despre versiunea clasică. Transformata Fourier este o metodă de transformare dintr-o „bază" în alta. Poți să te gândești la două baze ca la perspective diferite ale aceleiași probleme — ambele sunt moduri valide de a exprima o funcție, dar una sau cealaltă poate fi mai revelatoare, în funcție de problema în cauză. Câteva exemple de perechi de baze conectate prin transformata Fourier sunt poziția și momentul cinetic, respectiv timpul și frecvența.
Să vedem un exemplu despre cum ne poate ajuta transformata Fourier să determinăm ce notă cântă un instrument pe baza formei de undă audio. De obicei, vedem formele de undă reprezentate în baza timp — adică amplitudinea undei este exprimată ca funcție de timp.

Putem aplica transformata Fourier acestei forme de undă pentru a trece din baza timp în baza frecvență:

În baza frecvență, putem vedea cu ușurință un vârf clar la aproximativ 260 Hz. Acesta este un Do central!
Acum, poate ai fi reușit să determini că se cânta un Do central fără să folosești transformata Fourier, dar ce se întâmplă dacă mai multe note sunt cântate simultan? Atunci forma de undă devine mai complicată atunci când o reprezentăm în baza timp:

Dar spectrul de frecvență identifică clar trei vârfuri:

Acesta a fost un acord Do major, cântând notele Do, Mi și Sol.
Acest tip de analiză Fourier ne poate ajuta să extragem componentele de frecvență ale oricărui semnal complicat.
Transformata Fourier discretă
Transformata Fourier este utilă pentru numeroase aplicații de procesare a semnalelor. Dar în majoritatea acestor aplicații din lumea reală (inclusiv exemplul muzical de mai sus), dorim să transformăm un set discret de puncte de date — nu o funcție continuă. În acest caz, folosim transformata Fourier discretă. Transformata Fourier discretă (DFT) acționează asupra unui vector și îl mapează la vectorul conform formulei:
unde luăm . (Rețineți că există și alte convenții care au un semn minus în exponent, deci fii atent când întâlnești DFT în practică.) Reamintim că este o funcție periodică, cu perioada . Astfel, prin înmulțirea cu această funcție, transformata Fourier este, în esență, o modalitate de a descompune funcția (discretă) într-o combinație liniară a funcțiilor periodice constitutive, fiecare cu perioada .
Transformata Fourier cuantică
Acum am văzut cum transformata Fourier este folosită pentru a reprezenta o funcție ca o combinație liniară a unui nou set de „funcții de bază". Transformările de bază se fac regulat și pe stările Qubit. De exemplu, starea unui singur Qubit poate fi exprimată în baza computațională , cu stările de bază și , sau în baza cu stările de bază și . Ambele sunt la fel de valide, dar una poate fi mai naturală decât cealaltă, în funcție de tipul de problemă pe care încerci să o rezolvi.
Stările Qubit pot fi exprimate și în baza Fourier, unde o stare este exprimată în funcție de o combinație liniară a stărilor de bază Fourier , mai degrabă decât stările de bază computaționale obișnuite, . Pentru a face acest lucru, trebuie să aplici o transformată Fourier cuantică (QFT):
cu ca mai sus, iar este numărul de stări de bază din sistemul tău cuantic. Rețineți că, deoarece lucrăm acum cu Qubiți, Qubiți îți dau stări de bază, deci . Aici, stările de bază sunt scrise ca un singur număr unde variază de la la , dar mai frecvent vei vedea stările de bază exprimate ca , , , ..., , unde fiecare cifră binară reprezintă starea Qubitului 0 până la , de la dreapta la stânga. Există o modalitate simplă de a converti aceste stări binare la un singur număr: tratează-le pur și simplu ca numere binare! Deci, , , , , și așa mai departe, până la .
Construiește intuiția pentru stările de bază Fourier
Deci, tocmai am trecut în revistă care sunt stările de bază computaționale și cum sunt ordonate: sunt setul de stări în care fiecare Qubit este fie în , fie în , și le ordonăm de la starea în care toți Qubiții sunt , , până la starea în care sunt toți , .
Dar cum putem înțelege stările de bază Fourier? Toate stările de bază Fourier sunt superpoziții egale ale tuturor stărilor de bază computaționale, dar fiecare stare diferă de celelalte prin periodicitatea fazei componentelor. Pentru a înțelege acest lucru mai concret, să aruncăm o privire la cele patru stări de bază Fourier ale unui sistem cu doi Qubiți. Cea mai joasă stare Fourier este cea a cărei fază nu variază deloc:
Putem vizualiza această stare reprezentând amplitudinea complexă a fiecăruia dintre termeni. Linia roșie ghidează ochiul pentru a-ți arăta cum faza acestei amplitudini se răsucește în jurul planului complex ca funcție a stării de bază computaționale. Pentru , faza rămâne constantă:

Următoarea stare de bază Fourier este cea ale cărei faze ale componentelor se răsucesc de la la o singură dată:
Și putem vedea această răsucire în graficul amplitudinii complexe față de starea de bază computațională:

Deci, fiecare stare are o fază cu radiani mai mare decât starea anterioară, când sunt ordonate în mod standard, deoarece în acest exemplu avem patru stări de bază (). Următoarea stare de bază se răsucește de la 0 la de două ori:

În sfârșit, cea mai înaltă componentă Fourier este cea cu faza variind cel mai rapid. Pentru exemplul nostru cu doi Qubiți, este cea ale cărei faze se răsucesc de la 0 la de trei ori:

În general, pentru o stare cu Qubiți, vor exista stări de bază Fourier, a căror frecvență în variația fazei variază de la constantă, pentru , la rapid variabilă pentru , completând răsuciri în jurul lui peste superpoziția de stări. Deci, când aplicăm QFT unui stat cuantic, facem practic aceeași analiză de bază pe care am făcut-o pentru forma de undă muzicală în Introducere. Determinăm componentele de frecvență Fourier care contribuie la crearea stării cuantice de interes.
Încearcă câteva exemple de QFT-uri
Să continuăm să ne construim intuiția pentru transformata cuantică Fourier prin crearea unui stare în baza computațională, apoi să vedem ce se întâmplă când aplicăm QFT-ul asupra ei. Deocamdată, vom trata QFT-ul ca pe o cutie neagră pe care o aplicăm folosind QFTGate din biblioteca de circuite Qiskit. Mai târziu, vom arunca o privire sub capotă pentru a vedea cum este implementat.
Începem prin a încărca pachetele necesare și a selecta un dispozitiv pe care să rulăm Circuit-ul nostru:
import numpy as np
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from qiskit.circuit.library import QFTGate
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
# Load the Runtime primitive and session
from qiskit_ibm_runtime import SamplerV2 as Sampler
service = QiskitRuntimeService()
# Use the least busy backend
# backend = service.least_busy(operational=True, simulator=False, min_num_qubits = 127)
backend = service.backend("ibm_pinguino2")
print(backend.name)
ibm_pinguino2
Dacă nu ai timp disponibil în contul tău sau dorești să folosești un simulator din orice motiv, poți rula celula de mai jos pentru a configura un simulator care va imita dispozitivul cuantic selectat anterior:
# Load the backend sampler
from qiskit.primitives import BackendSamplerV2
# Load the Aer simulator and generate a noise model based on the currently-selected backend.
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel
noise_model = NoiseModel.from_backend(backend)
# Define a simulator using Aer, and use it in Sampler.
backend_sim = AerSimulator(noise_model=noise_model)
sampler_sim = BackendSamplerV2(backend=backend_sim)
# Alternatively, load a fake backend with generic properties and define a simulator.
from qiskit.providers.fake_provider import GenericBackendV2
backend_gen = GenericBackendV2(num_qubits=18)
sampler_gen = BackendSamplerV2(backend=backend_gen)
O singură stare din baza computațională
Mai întâi, să încercăm să transformăm o singură stare din baza computațională. Vom începe prin a crea o stare computațională aleatoare:
# Step 1: Map
qubits = 4
N = 2**qubits
qc = QuantumCircuit(qubits)
# flip state of random qubits to put in a random single computational basis state
for i in range(1, qubits):
if np.random.randint(0, 2):
qc.x(i)
# make a copy of the above circuit. (to be used when we apply the QFT in next part)
qc_qft = qc.copy()
qc.measure_all()
qc.draw("mpl")
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
# Step 3: Run the job on a real quantum computer OR try fake backend
sampler = Sampler(mode=backend)
pubs = [qc_isa]
# Run the job on real quantum device
job = sampler.run(pubs, shots=1000)
res = job.result()
counts = res[0].data.meas.get_counts()
# OR Run the job on the Aer simulator with noise model from real backend
# job = sampler_sim.run([qc_isa])
# res = job.result()
# counts = res[0].data.meas.get_counts()
# Step 4: Post-Process
plot_histogram(counts)
Acum, să transformăm Fourier această stare folosind QFTGate:
# Step 1: Map
qc_qft.compose(QFTGate(qubits), inplace=True)
qc_qft.measure_all()
qc_qft.draw("mpl")
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc_qft)
# Step 3: Run the job on a real quantum computer - try fake backend
sampler = Sampler(mode=backend)
pubs = [qc_isa]
# Run the job on real quantum device
job = sampler.run(pubs, shots=1000)
res = job.result()
counts = res[0].data.meas.get_counts()
# OR Run the job on the Aer simulator with noise model from real backend
# job = sampler_sim.run([qc_isa])
# res = job.result()
# counts = res[0].data.meas.get_counts()
# Step 4: Post-Process
plot_histogram(counts)
După cum poți vedea, măsurăm populațiile fiecărei stări ca fiind mai mult sau mai puțin egale, cu mici variații datorate zgomotului experimental și statistic. Deci, dacă aplici QFT-ul unui singur stat din baza computațională, rezultatul este o superpozitie egală a tuturor stărilor. Dacă ești familiarizat cu transformatele Fourier, acest lucru probabil nu te surprinde. Un principiu de bază care ne poate ajuta să construim o legătură intuitivă între o funcție și transformata sa Fourier este că lățimea unei funcții este invers proporțională cu lățimea transformatei sale Fourier. Deci, ceva foarte localizat în timp, de exemplu, ca un impuls foarte scurt, va necesita o gamă largă de frecvențe pentru a genera acel impuls. Acel semnal va fi foarte larg în spațiul Fourier.
Acest fapt este de fapt legat de incertitudinea cuantică! Principiul incertitudinii al lui Heisenberg este enunțat de obicei ca . Deci, dacă incertitudinea în () este mică, incertitudinea în impuls () trebuie să fie mare, și invers. Se dovedește că trecerea din baza de poziție în baza de impuls se realizează printr-o transformată Fourier.
Notă: Ține minte că măsurăm populațiile în fiecare dintre stările de bază, deci pierdem informații despre fazele relative dintre diferitele părți ale superpozitiei. Deci, deși QFT-ul oricărui singur stat din baza computațională va produce aceeași distribuție egală a populației peste toate stările de bază, fazele nu vor fi neapărat aceleași.