Ansaetze și forme variationale
În centrul tuturor algoritmilor variationale se află ideea cheie de a analiza diferențele dintre stări, care sunt legate convenabil printr-o mapare bine comportată (de exemplu, continuă, diferențiabilă) dintr-un set de parametri sau variabile — de unde și numele.
Mai întâi, vom explora cum să construim circuite parametrizate manual. Vom folosi aceste circuite pentru a defini o formă variatională ce reprezintă o colecție de stări parametrizate pe care algoritmul nostru variational le va explora. Apoi, vom construi ansatz-ul nostru aplicând această formă variatională asupra stării de referință.
Vom explora, de asemenea, cum să facem compromisuri între viteză și acuratețe în timp ce explorăm acest spațiu de căutare.
Circuite Cuantice Parametrizate
Algoritmii variationale funcționează explorând și comparând o gamă de stări cuantice , care depind de un set finit de parametri . Aceste stări pot fi pregătite folosind un circuit cuantic parametrizat, unde porțile sunt definite cu parametri reglabili. Este posibil să creezi acest circuit parametrizat fără a lega unghiuri specifice încă:
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit rustworkx
from qiskit.circuit import QuantumCircuit, Parameter
theta = Parameter("θ")
qc = QuantumCircuit(3)
qc.rx(theta, 0)
qc.cx(0, 1)
qc.x(2)
qc.draw("mpl")
from math import pi
angle_list = [pi / 3, pi / 2]
circuits = [qc.assign_parameters({theta: angle}) for angle in angle_list]
for circuit in circuits:
display(circuit.draw("mpl"))
Formă Variatională și Ansatz
Pentru a optimiza iterativ de la o stare de referință la o stare țintă , trebuie să definim o formă variatională ce reprezintă o colecție de stări parametrizate pe care algoritmul nostru variational le va explora:
Observă că starea parametrizată depinde atât de starea de referință , care nu depinde de niciun parametru, cât și de forma variatională , care depinde întotdeauna de parametri. Ne referim la combinația acestor două jumătăți ca un ansatz: .
Pe măsură ce construim ansatz-ul nostru pentru a reprezenta o colecție de stări parametrizate pe care algoritmul nostru variational le va explora, realizăm o problemă importantă: dimensionalitatea. Un sistem de qubiți (adică, spațiul Hilbert) are un număr vast de stări cuantice distincte în spațiul de configurație. Ar fi nevoie de un număr incomod de mare de parametri pentru a-l explora complet. Cantitativ, dimensionalitatea sa este . Pentru a înrăutăți lucrurile, complexitatea de execuție a algoritmilor de căutare și a altora similari crește exponențial cu această dimensionalitate, un fenomen adesea numit în literatura de specialitate blestemul dimensionalității.
Pentru a contracara acest inconvenient, este o practică obișnuită să se impună unele constrângeri rezonabile asupra formei variationale, astfel încât să fie explorate doar cele mai relevante stări. Găsirea unui ansatz trunchiat eficient este un domeniu activ de cercetare, dar vom acoperi două modele comune.
Ansaetze euristice și compromisuri
Dacă nu ai nicio informație despre problema ta particulară care să poată ajuta la reducerea dimensionalității, poți încerca o familie arbitrară de circuite parametrizate cu mai puțin de parametri. Cu toate acestea, există câteva compromisuri de luat în considerare:
- Viteză: Prin reducerea spațiului de căutare, algoritmul poate rula mai rapid.
- Acuratețe: Reducerea spațiului ar putea risca excluderea soluției reale a problemei, ducând la soluții sub-optime.
- Zgomot: Circuitele mai adânci sunt afectate de zgomot, așa că trebuie să experimentăm cu conectivitatea, porțile și fidelitatea porților ansatz-ului nostru.
Există un compromis fundamental între calitate (sau chiar rezolvabilitate) și viteză: cu cât sunt mai mulți parametri, cu atât este mai probabil să găsești un rezultat precis, dar va dura mai mult timp să rulezi algoritmul.
Circuite N-locale
Unul dintre cele mai utilizate exemple de ansaetze euristice sunt circuitele N-locale, din câteva motive:
- Implementare eficientă: Ansatz-ul N-local este de obicei compus din porți simple, locale, care pot fi implementate eficient pe un calculator cuantic, folosind un număr mic de qubiți fizici. Acest lucru face mai ușoară construcția și optimizarea circuitelor cuantice.
- Surprinde corelații importante: Ansatz-ul N-local poate surprinde corelații importante între qubiții dintr-un sistem cuantic, chiar și cu un număr mic de porți. Aceasta se datorează faptului că porțile locale pot acționa asupra qubiților vecini și pot crea entanglament între ei, ceea ce poate fi important pentru simularea sistemelor cuantice complexe.
Aceste circuite constau din straturi de rotație și entanglament care se repetă alternativ de una sau mai multe ori, astfel:
- Fiecare strat este format din porți de dimensiune cel mult , unde trebuie să fie mai mic decât numărul de qubiți.
- Pentru un strat de rotație, porțile sunt stivuite una peste alta. Putem folosi operații de rotație standard, cum ar fi
RXsauCRZ. - Pentru un strat de entanglament, putem folosi porți precum porțile
ToffolisauCXcu o strategie de entanglament. - Ambele tipuri de straturi pot fi parametrizate sau nu, dar cel puțin unul dintre ele trebuie să conțină parametri. Altfel, fără cel puțin un parametru, nu ar exista nicio variație!
- Opțional, un strat suplimentar de rotație este adăugat la sfârșitul circuitului.
De exemplu, să creăm un circuit NLocal cu cinci qubiți, cu blocuri de rotație formate din porți RX și CRZ, blocuri de entanglament formate din porți Toffoli care acționează pe qubiții , , și , și repetări ale fiecărui strat.
from qiskit.circuit.library import NLocal, CCXGate, CRZGate, RXGate
from qiskit.circuit import Parameter
theta = Parameter("θ")
ansatz = NLocal(
num_qubits=5,
rotation_blocks=[RXGate(theta), CRZGate(theta)],
entanglement_blocks=CCXGate(),
entanglement=[[0, 1, 2], [0, 2, 3], [4, 2, 1], [3, 1, 0]],
reps=2,
insert_barriers=True,
)
ansatz.decompose().draw("mpl")
În exemplul de mai sus, cea mai mare poartă este poarta Toffoli, care acționează pe trei qubiți, făcând circuitul -local. Cel mai frecvent utilizat tip de circuite -locale sunt circuitele -locale cu porți de rotație pe un singur qubit și porți de entanglament pe qubiți.
Să creăm un circuit -local folosind clasa TwoLocal din Qiskit. Sintaxa este aceeași ca pentru NLocal, dar există câteva diferențe. De exemplu, majoritatea porților, cum ar fi RX, RZ și CNOT, pot fi transmise ca șiruri de caractere fără a importa porțile sau a crea o instanță Parameter.
from qiskit.circuit.library import TwoLocal
ansatz = TwoLocal(
num_qubits=5,
rotation_blocks=["rx", "rz"],
entanglement_blocks="cx",
entanglement="linear",
reps=2,
insert_barriers=True,
)
ansatz.decompose().draw("mpl")
În acest caz, am folosit distribuția de entanglament liniară, unde fiecare qubit este entanglat cu următorul. Pentru a afla despre alte strategii, consultă documentația TwoLocal.
Efficient SU2
efficient_su2 este un circuit eficient din punct de vedere hardware, care constă din straturi de operații pe un singur qubit ce acoperă SU(2) și entanglamente CX. Acesta este un șablon euristic ce poate fi folosit pentru a pregăti funcții de undă de probă pentru algoritmii cuantici variationale sau ca un circuit de clasificare pentru învățarea automată.
from qiskit.circuit.library import efficient_su2
ansatz = efficient_su2(4, su2_gates=["rx", "y"], entanglement="linear", reps=1)
ansatz.decompose().draw("mpl")
Ansaetze specifice problemei
În timp ce ansaetze euristice și eficiente din punct de vedere hardware ne ajută să rezolvăm o problemă într-un mod naiv, putem folosi cunoștințe specifice problemei pentru a restrânge spațiul de căutare al circuitului la un tip specific. Aceasta ne va ajuta să câștigăm viteză fără a pierde acuratețe în procesul de căutare.
Optimizare
Într-o problemă de tăiere maximă (max-cut), vrem să partitionăm nodurile unui graf în așa fel încât să maximizăm numărul de muchii dintre nodurile din grupuri diferite. Partiționarea maximă dorită pentru graful de mai jos este clară: nodul 0 din stânga ar trebui separat de restul nodurilor din dreapta printr-o tăietură.
import rustworkx as rx
from rustworkx.visualization import mpl_draw
n = 4
G = rx.PyGraph()
G.add_nodes_from(range(n))
# The edge syntax is (start, end, weight)
edges = [(0, 1, 1.0), (0, 2, 1.0), (0, 3, 1.0), (1, 2, 1.0), (2, 3, 1.0)]
G.add_edges_from(edges)
mpl_draw(
G, pos=rx.shell_layout(G), with_labels=True, edge_labels=str, node_color="#1192E8"
)
Pentru a utiliza algoritmul QAOA pentru o problemă de tăiere maximă, avem nevoie de un Hamiltonian Pauli care codifică costul în așa fel încât valoarea de așteptare minimă a operatorului să corespundă numărului maxim de muchii dintre nodurile din două grupuri diferite.
Pentru acest exemplu simplu, operatorul este o combinație liniară de termeni cu operatori Z pe nodurile conectate printr-o muchie (reamintește că qubit-ul 0 este cel mai îndepărtat la dreapta): . Odată ce operatorul este construit, ansatz-ul pentru algoritmul QAOA poate fi ușor construit folosind circuitul QAOAAnsatz din biblioteca de circuite Qiskit.
# Pre-defined ansatz circuit, operator class and visualization tools
from qiskit.circuit.library import QAOAAnsatz
from qiskit.quantum_info import SparsePauliOp
# Problem to Hamiltonian operator
hamiltonian = SparsePauliOp.from_list(
[("ZZII", 1), ("IZZI", 1), ("ZIIZ", 1), ("IZIZ", 1), ("IIZZ", 1)]
)
# QAOA ansatz circuit
ansatz = QAOAAnsatz(hamiltonian, reps=2)
# Draw
ansatz.decompose(reps=3).draw("mpl")
Imaginea anterioară ilustrează ansatz-ul în porți de bază pentru claritate. Cu toate acestea, poate fi exprimat în mai multe niveluri de descompunere prin modificarea argumentului reps sau prin desenarea circuitului fără metoda de descompunere. De exemplu, următoarea reprezentare arată direct structura QAOA cu valoarea implicită a argumentului reps, care este reps=1.
ansatz.decompose(reps=2).draw("mpl")
Învățare Automată Cuantică
În învățarea automată, o aplicație frecventă este clasificarea datelor în două sau mai multe categorii. Aceasta implică codificarea unui punct de date într-o hartă de caracteristici care mapează vectorii de caracteristici clasici în spațiul Hilbert cuantic. Construirea hărților de caracteristici cuantice bazate pe circuite cuantice parametrizate care sunt dificil de simulat clasic este un pas important către obținerea unui avantaj potențial față de abordările de învățare automată clasică și este un domeniu activ de cercetare actuală.
zz_feature_map poate fi folosit pentru a crea un circuit parametrizat. Putem transmite punctele noastre de date către harta de caracteristici () și o formă variatională separată pentru a transmite ponderile ca parametri ().
from qiskit.circuit.library import zz_feature_map, TwoLocal
data = [0.1, 0.2]
zz_feature_map_reference = zz_feature_map(feature_dimension=2, reps=2)
zz_feature_map_reference = zz_feature_map_reference.assign_parameters(data)
variation_form = TwoLocal(2, ["ry", "rz"], "cz", reps=2)
vqc_ansatz = zz_feature_map_reference.compose(variation_form)
vqc_ansatz.decompose().draw("mpl")
Rezumat
Cu această lecție, ai învățat cum să îți definești spațiul de căutare cu o formă variatională:
- Pregătești stări cu un circuit cuantic parametrizat, unde porțile sunt definite cu parametri reglabili
- Cum să construiești ansaetze care fac compromisuri între viteză și acuratețe
- Ansaetze euristice
- Ansaetze specifice problemei
Sarcina noastră variatională de nivel înalt arată astfel:
Pentru fiecare parametru variational , va fi produsă o stare cuantică diferită. Pentru a găsi parametrii optimi, trebuie să definim o funcție de cost specifică problemei pentru a actualiza iterativ parametrii ansatz-ului nostru.