Ansaetze and variational forms
U podstaw wszystkich algorytmów wariacyjnych leży kluczowa idea analizowania różnic między stanami, które są wygodnie powiązane za pomocą pewnego dobrze zachowującego się odwzorowania (na przykład ciągłego, różniczkowalnego) ze zbioru parametrów lub zmiennych — stąd nazwa.
Na początku przyjrzymy się, jak ręcznie konstruować sparametryzowane obwody. Użyjemy tych obwodów do zdefiniowania variational form, która reprezentuje kolekcję sparametryzowanych stanów do eksploracji przez nasz algorytm wariacyjny. Następnie skonstruujemy nasz ansatz, stosując tę variational form do naszego stanu referencyjnego.
Zbadamy też, jak wyważyć szybkość i dokładność podczas eksploracji tej przestrzeni poszukiwań.
Parameterized Quantum Circuits
Algorytmy wariacyjne działają poprzez eksplorowanie i porównywanie szeregu stanów kwantowych , które zależą od skończonego zbioru parametrów . Stany te można przygotować za pomocą sparametryzowanego obwodu kwantowego (PQC), w którym bramki są definiowane z regulowanymi parametrami. Możliwe jest utworzenie takiego sparametryzowanego obwodu bez wcześniejszego przypisywania konkretnych kątów:
# 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"))
Variational Form and Ansatz
Aby iteracyjnie optymalizować od stanu referencyjnego do stanu docelowego , musimy zdefiniować variational form , która reprezentuje kolekcję sparametryzowanych stanów do eksploracji przez nasz algorytm wariacyjny:
Zauważ, że sparametryzowany stan zależy zarówno od stanu referencyjnego , który nie zależy od żadnych parametrów, jak i od variational form , która zawsze zależy od parametrów. Kombinację tych dwóch części nazywamy ansatzem: .
Konstruując nasz ansatz tak, aby reprezentował kolekcję sparametryzowanych stanów do eksploracji przez algorytm wariacyjny, napotykamy istotny problem: wymiarowość. System -qubitowy (czyli przestrzeń Hilberta) zawiera ogromną liczbę różnych stanów kwantowych w przestrzeni konfiguracyjnej. Do jej pełnej eksploracji potrzebowalibyśmy nieporęcznie dużej liczby parametrów. Ilościowo wymiarowość wynosi . Co gorsza, złożoność obliczeniowa algorytmów przeszukiwania i podobnych rośnie wykładniczo wraz z tą wymiarowością — zjawisko to często określa się w literaturze mianem przekleństwa wymiarowości.
Aby zaradzić temu problemowi, powszechną praktyką jest nakładanie rozsądnych ograniczeń na variational form tak, aby eksplorować tylko najbardziej istotne stany. Znalezienie efektywnego obciętego ansatzu jest aktywnym obszarem badań, ale omówimy dwa popularne podejścia.
Heuristic ansaetze and trade-offs
Jeśli nie masz żadnych informacji o swoim konkretnym problemie, które mogłyby pomóc ograniczyć wymiarowość, możesz wypróbować dowolną rodzinę sparametryzowanych obwodów z liczbą parametrów mniejszą niż . Należy jednak wziąć pod uwagę pewne kompromisy:
- Szybkość: Zmniejszając przestrzeń poszukiwań, algorytm może działać szybciej.
- Dokładność: Zawężenie przestrzeni może skutkować wykluczeniem rzeczywistego rozwiązania problemu, prowadząc do suboptymalnych wyników.
- Szumy: Głębsze Circuit są bardziej podatne na szumy, dlatego musimy eksperymentować z połączeniami, bramkami i wiernością bramek naszego ansatzu.
Istnieje fundamentalny kompromis między jakością (a nawet wykonalnością) a szybkością: im więcej parametrów, tym większe prawdopodobieństwo uzyskania dokładnego wyniku, ale tym dłużej będzie działał algorytm.
N-local circuits
Jednym z najszerzej stosowanych przykładów heurystycznych ansaetze są N-local circuits, i to z kilku powodów:
- Efektywna implementacja: Ansatz N-lokalny składa się zazwyczaj z prostych, lokalnych bramek, które można efektywnie zaimplementować na komputerze kwantowym, wykorzystując niewielką liczbę fizycznych qubitów. Ułatwia to konstruowanie i optymalizację Circuit kwantowych.
- Uchwytuje istotne korelacje: Ansatz N-lokalny potrafi uchwycić ważne korelacje między qubitami w układzie kwantowym, nawet przy małej liczbie bramek. Wynika to z faktu, że lokalne bramki mogą działać na sąsiadujących qubitach i tworzyć między nimi splątanie, co może być istotne przy symulowaniu złożonych układów kwantowych.
Obwody te składają się z naprzemiennie powtarzanych (jeden lub więcej razy) warstw rotacji i warstw splątania:
- Każda warstwa jest tworzona przez bramki o rozmiarze co najwyżej , gdzie musi być mniejsze od liczby qubitów.
- W warstwie rotacji bramki są układane jedna na drugiej. Można używać standardowych operacji rotacji, takich jak
RXlubCRZ. - W warstwie splątania można używać bramek takich jak bramki
ToffolilubCXze strategią splątania. - Oba typy warstw mogą być sparametryzowane lub nie, ale co najmniej jedna z nich musi zawierać parametry. W przeciwnym razie bez choćby jednego parametru nie byłoby żadnych wariacji!
- Opcjonalnie na końcu obwodu dodaje się dodatkową warstwę rotacji.
Na przykład utwórzmy pięcio-qubitowy obwód NLocal z blokami rotacji złożonymi z bramek RX i CRZ, blokami splątania złożonymi z bramek Toffoli działających na qubitach , , i oraz powtórzeniami każdej warstwy.
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")
W powyższym przykładzie największą bramką jest bramka Toffoli działająca na trzech qubitach, co czyni obwód -lokalnym. Najczęściej stosowanym typem obwodów -lokalnych są obwody -lokalne z jednokubitowymi bramkami rotacji i -kubitowymi bramkami splątania.
Utwórzmy obwód -lokalny, korzystając z klasy TwoLocal w Qiskit. Składnia jest taka sama jak w NLocal, ale istnieją pewne różnice. Na przykład większość bramek, takich jak RX, RZ i CNOT, można przekazywać jako łańcuchy znaków bez importowania bramek ani tworzenia instancji 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")
W tym przypadku użyliśmy liniowego rozkładu splątania, w którym każdy qubit jest splątany z następnym. Aby dowiedzieć się więcej o innych strategiach, zajrzyj do dokumentacji TwoLocal.
Efficient SU2
efficient_su2 to hardware-efficient Circuit składający się z warstw jednokubitowych operacji obejmujących SU(2) oraz splątań CX. Jest to heurystyczny wzorzec, który można wykorzystać do przygotowywania próbnych funkcji falowych dla wariacyjnych algorytmów kwantowych lub jako Circuit klasyfikacyjny w uczeniu maszynowym.
from qiskit.circuit.library import efficient_su2
ansatz = efficient_su2(4, su2_gates=["rx", "y"], entanglement="linear", reps=1)
ansatz.decompose().draw("mpl")
Ansaetze specyficzne dla problemu
Podczas gdy heurystyczne i sprzętowo wydajne ansaetze pomagają nam rozwiązać problem w naiwny sposób, możemy wykorzystać wiedzę specyficzną dla danego problemu, aby zawęzić przestrzeń przeszukiwania Circuit do konkretnego typu. Pozwoli nam to zyskać na szybkości bez utraty dokładności w procesie przeszukiwania.
Optymalizacja
W problemie max-cut chcemy podzielić węzły grafu w taki sposób, aby zmaksymalizować liczbę krawędzi między węzłami należącymi do różnych grup. Pożądany podział max-cut dla poniższego grafu jest oczywisty: węzeł 0. po lewej stronie powinien zostać oddzielony od pozostałych węzłów po prawej stronie cięciem.
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"
)
Aby wykorzystać algorytm QAOA do rozwiązania problemu max-cut, potrzebujemy Hamiltonianu Pauliego, który koduje koszt w taki sposób, że minimalna wartość oczekiwana operatora odpowiada maksymalnej liczbie krawędzi między węzłami należącymi do dwóch różnych grup.
W tym prostym przykładzie operator jest liniową kombinacją wyrazów z operatorami Z na węzłach połączonych krawędzią (pamiętaj, że 0. qubit jest najbardziej po prawej): . Po skonstruowaniu operatora ansatz dla algorytmu QAOA można łatwo zbudować za pomocą Circuit QAOAAnsatz z biblioteki Circuit 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")
Poprzedni obraz przedstawia ansatz w podstawowych Gate'ach dla większej przejrzystości. Można go jednak wyrazić na wielu poziomach dekompozycji, zmieniając argument reps lub rysując Circuit bez metody decompose. Na przykład poniższa reprezentacja bezpośrednio pokazuje strukturę QAOA z domyślną wartością reps, czyli reps=1.
ansatz.decompose(reps=2).draw("mpl")
Kwantowe uczenie maszynowe
W uczeniu maszynowym powszechnym zastosowaniem jest klasyfikacja danych do dwóch lub więcej kategorii. Polega to na zakodowaniu punktu danych w feature map, która odwzorowuje klasyczne wektory cech w kwantową przestrzeń Hilberta. Konstruowanie kwantowych feature map opartych na parametryzowanych Circuit kwantowych, które są trudne do symulacji klasycznie, jest ważnym krokiem w kierunku uzyskania potencjalnej przewagi nad klasycznymi metodami uczenia maszynowego i stanowi aktywny obszar bieżących badań.
zz_feature_map może być używany do tworzenia parametryzowanego Circuit. Możemy przekazać nasze punkty danych do feature map () oraz oddzielną formę wariacyjną, aby przekazać wagi jako parametry ().
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")
Podsumowanie
Dzięki tej lekcji nauczyłeś się, jak definiować przestrzeń przeszukiwania za pomocą formy wariacyjnej:
- Przygotowywać stany za pomocą parametryzowanego Circuit kwantowego, w którym Gate'y są zdefiniowane z przestrajalnymi parametrami
- Jak konstruować ansaetze z kompromisem między szybkością a dokładnością
- Heurystyczne ansaetze
- Ansaetze specyficzne dla problemu
Nasz ogólny wariant wariacyjny wygląda następująco:
Dla każdego parametru wariacyjnego powstanie inny stan kwantowy. Aby znaleźć optymalne parametry, musimy zdefiniować funkcję kosztu zależną od problemu, która iteracyjnie aktualizuje parametry naszego ansatzu.