Skip to main content
IBM Quantum Platform

Ansätze und Variationsformen

Das Herzstück aller Variationsalgorithmen besteht in der Analyse der Unterschiede zwischen den Zuständen, die durch eine geeignete Abbildung (z. B. kontinuierlich, differenzierbar) aus einer Reihe von Parametern oder Variablen miteinander verbunden sind - daher der Name.

Zunächst werden wir untersuchen, wie parametrisierte Schaltungen von Hand konstruiert werden können. Wir werden diese Schaltkreise verwenden, um eine Schichten von parametrisierten Gattern, die eine bestimmte Anzahl von Malen wiederholt werden, und die Parameter der Gatter werden während des Algorithmus optimiert, um die Kostenfunktion zu minimieren. zu definieren, die eine Sammlung von parametrisierten Zuständen darstellt, die unser Variationsalgorithmus untersuchen kann. Dann konstruieren wir unsere Kombination aus einem Referenzoperator und einer Variationsform zur Beschreibung des Suchraums, den wir erkunden., indem wir diese Variationsform auf unseren Referenzzustand anwenden.

Wir werden auch untersuchen, wie man bei der Erkundung dieses Suchraums zwischen Geschwindigkeit und Genauigkeit abwägen kann.

Ein Diagramm, das die wichtigsten Komponenten der Ansatzdiskussion zeigt, einschließlich heuristischer Ansätze und problemspezifischer Ansätze.

Parametrisierte Quantenschaltungen

Variationsalgorithmen arbeiten, indem sie eine Reihe von Quantenzuständen ∣ψ(θ⃗)⟩|\psi(\vec{\theta})\rangle untersuchen und vergleichen, die von einer endlichen Reihe von kk Parametern θ⃗=(θ0,…,θk−1)\vec{\theta} = (\theta^0, \ldots, \theta^{k-1}) abhängen. Diese Zustände können mithilfe eines parametrisierten Quantenschaltkreises vorbereitet werden, in dem Gatter mit abstimmbaren Parametern definiert sind. Es ist möglich, diese parametrisierte Schaltung zu erstellen, ohne bestimmte Winkel zu binden:

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")

Output:

Output of the previous code cell
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"))

Output:

Output of the previous code cell Output of the previous code cell

Variationsform und Ansatz

Um iterativ von einem Referenzzustand ∣ρ⟩|\rho\rangle zu einem Zielzustand ∣ψ(θ⃗)⟩|\psi(\vec\theta)\rangle zu optimieren, müssen wir eine Variationsform UV(θ⃗)U_V(\vec{\theta}) definieren, die eine Sammlung von parametrisierten Zuständen darstellt, die unser Variationsalgorithmus untersuchen soll:

∣0⟩→URUR∣0⟩=∣ρ⟩→UV(θ⃗)UA(θ⃗)∣0⟩=UV(θ⃗)UR∣0⟩=UV(θ⃗)∣ρ⟩=∣ψ(θ⃗)⟩\begin{aligned} |0\rangle \xrightarrow{U_R} U_R|0\rangle & = |\rho\rangle \xrightarrow{U_V(\vec{\theta})} U_A(\vec{\theta})|0\rangle \\[1mm] & = U_V(\vec{\theta})U_R|0\rangle \\[1mm] & = U_V(\vec{\theta})|\rho\rangle \\[1mm] & = |\psi(\vec{\theta})\rangle \\[1mm] \end{aligned}

Man beachte, dass der parametrisierte Zustand sowohl vom Referenzzustand ∣ρ⟩|\rho\rangle, der nicht von Parametern abhängt, als auch von der Variationsform UV(θ⃗)U_V(\vec{\theta}), die immer von Parametern abhängt, abhängt. Wir bezeichnen die Kombination dieser beiden Hälften als Ansatz: UA(θ⃗):=UV(θ⃗)URU_A(\vec\theta) := U_V(\vec\theta)U_R.

Während wir unseren Ansatz konstruieren, um eine Sammlung von parametrisierten Zuständen darzustellen, die unser Variationsalgorithmus untersuchen kann, erkennen wir ein wichtiges Problem: die Dimensionalität. Ein nn -Qubit-System (d.h. ein Hilbert-Raum) hat eine große Anzahl von unterschiedlichen Quantenzuständen im Konfigurationsraum. Wir bräuchten eine unüberschaubare Anzahl von Parametern, um sie vollständig zu erforschen. Quantitativ gesehen ist seine Dimensionalität D=22nD = 2^{2n}. Erschwerend kommt hinzu, dass die Laufzeitkomplexität von Suchalgorithmen und anderen Algorithmen mit dieser Dimensionalität exponentiell zunimmt, ein Phänomen, das in der Literatur häufig als Fluch der Dimensionalität bezeichnet wird.

Um diesem Nachteil entgegenzuwirken, ist es üblich, der Variationsform einige vernünftige Beschränkungen aufzuerlegen, so dass nur die wichtigsten Zustände untersucht werden. Die Suche nach einem effizienten verkürzten Ansatz ist ein aktives Forschungsgebiet, aber wir werden uns mit zwei gängigen Designs befassen.


Heuristische Ansätze und Kompromisse

Wenn Sie keine Informationen über Ihr spezielles Problem haben, die helfen können, die Dimensionalität einzuschränken, können Sie eine beliebige Familie von parametrisierten Schaltungen mit weniger als 22n2^{2n} Parametern versuchen. Allerdings gibt es einige Kompromisse zu beachten:

  • Geschwindigkeit : Durch die Verkleinerung des Suchraums kann der Algorithmus schneller laufen.
  • Genauigkeit : Bei einer Verkleinerung des Raums besteht die Gefahr, dass die eigentliche Lösung des Problems ausgeschlossen wird, was zu suboptimalen Lösungen führt.
  • Rauschen : Tiefere Schaltungen werden durch Rauschen beeinträchtigt, daher müssen wir mit der Konnektivität, den Gattern und der Gattertreue unseres Ansatzes experimentieren.

Es besteht ein grundlegender Kompromiss zwischen Qualität (oder sogar Lösbarkeit) und Geschwindigkeit: je mehr Parameter, desto wahrscheinlicher ist es, dass Sie ein präzises Ergebnis finden, aber desto länger dauert es, den Algorithmus auszuführen.

N-lokale Schaltungen

Eines der am weitesten verbreiteten Beispiele für heuristische Ansaetze sind die N-lokalen Schaltungen, und zwar aus mehreren Gründen:

  • Effiziente Implementierung : Der N-lokale Ansatz besteht typischerweise aus einfachen, lokalen Gattern, die auf einem Quantencomputer mit einer geringen Anzahl physikalischer Qubits effizient implementiert werden können. Dies erleichtert die Konstruktion und Optimierung von Quantenschaltungen.
  • Erfasst wichtige Korrelationen : Der N-lokale Ansatz kann wichtige Korrelationen zwischen den Qubits in einem Quantensystem erfassen, selbst bei einer geringen Anzahl von Gattern. Der Grund dafür ist, dass die lokalen Gatter auf benachbarte Qubits einwirken und eine Verschränkung zwischen ihnen erzeugen können, was für die Simulation komplexer Quantensysteme wichtig sein kann.

Diese Schaltungen bestehen aus Rotations- und Verschränkungsschichten, die abwechselnd ein- oder mehrmals wie folgt wiederholt werden:

  • Jede Schicht besteht aus Gattern mit einer Größe von höchstens NN, wobei NN kleiner sein muss als die Anzahl der Qubits.
  • Bei einer Rotationsschicht werden die Gates übereinander gestapelt. Wir können Standard-Rotationsoperationen verwenden, wie z. B RX oder CRZ.
  • Für eine Verschränkungsschicht können wir Gatter wie Toffoli gates oder CX mit einer Verschränkungsstrategie verwenden.
  • Beide Arten von Ebenen können parametrisiert oder nicht parametrisiert sein, aber mindestens eine von ihnen muss Parameter enthalten. Denn ohne mindestens einen Parameter gäbe es keine Variationen!
  • Optional kann am Ende der Schaltung eine zusätzliche Rotationsschicht hinzugefügt werden.

Erstellen wir zum Beispiel eine Fünf-Qubit-Schaltung NLocal schaltung mit Rotationsblöcken, die durch RX und CRZ gattern gebildeten Rotationsblöcken, von Toffoli Gattern gebildeten Verschränkungsblöcken, die auf die Qubits [0,1,2][0,1,2], [0,2,3][0,2,3], [4,2,1][4,2,1] und [3,1,0][3,1,0] und 22 Wiederholungen jeder Schicht wirken.

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")

Output:

Output of the previous code cell

Im obigen Beispiel ist das größte Gatter das Toffoli-Gatter, das auf drei Qubits wirkt, wodurch die Schaltung 33 -lokal wird. Die am häufigsten verwendete Art von NN -lokalen Schaltungen sind 22 -lokale Schaltungen mit Ein-Qubit-Rotationsgattern und 22 -Qubit-Verschränkungsgattern.

Erstellen wir eine 22 -lokale Schaltung unter Verwendung der Qiskit TwoLocal klasse. Die Syntax ist die gleiche wie die von NLocal. Es gibt jedoch einige Unterschiede. Zum Beispiel können die meisten Gates, wie RX, RZ und CNOT, als Strings übergeben werden, ohne dass die Gates importiert oder eine Parameter Instanz erstellt werden muss.

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")

Output:

Output of the previous code cell

In diesem Fall haben wir die lineare Verschränkungsverteilung verwendet, bei der jedes Qubit mit dem nächsten verschränkt ist. Informationen über andere Strategien finden Sie in der Dokumentation TwoLocal .

Effizienz SU2

efficient_su2 ist eine hardware-effiziente Schaltung, die aus Schichten von Ein-Qubit-Operationen besteht, die SU(2) und CX Verschränkungen umfassen. Dies ist ein heuristisches Muster, das zur Vorbereitung von Versuchswellenfunktionen für variierende Quantenalgorithmen oder als Klassifizierungsschaltung für das maschinelle Lernen verwendet werden kann.

from qiskit.circuit.library import efficient_su2

ansatz = efficient_su2(4, su2_gates=["rx", "y"], entanglement="linear", reps=1)
ansatz.decompose().draw("mpl")

Output:

Output of the previous code cell

Problemspezifische Ansätze

Während heuristische und hardware-effiziente Ansaetze uns helfen, ein Problem auf naive Weise zu lösen, können wir problemspezifisches Wissen nutzen, um unseren Schaltungssuchraum auf einen bestimmten Typ zu beschränken. Auf diese Weise können wir die Geschwindigkeit erhöhen, ohne dass wir bei der Suche an Genauigkeit verlieren.

Optimierung

Bei einem Max-Cut-Problem geht es darum, die Knoten eines Graphen so zu partitionieren, dass die Anzahl der Kanten zwischen Knoten in unterschiedlichen Gruppen maximiert wird. Die gewünschte Max-Cut-Partition für den untenstehenden Graphen ist klar: Der 0. Knoten auf der linken Seite sollte von den restlichen Knoten auf der rechten Seite durch einen Cut getrennt werden.

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"
)

Output:

Output of the previous code cell

Um den QAOA-Algorithmus für ein Max-Cut-Problem einzusetzen, benötigen wir einen Pauli-Hamiltonian, der die Kosten so kodiert, dass der minimale Erwartungswert des Operators der maximalen Anzahl von Kanten zwischen den Knoten in zwei verschiedenen Gruppen entspricht.

In diesem einfachen Beispiel ist der Operator eine Linearkombination von Termen mit Z-Operatoren auf Knoten, die durch eine Kante verbunden sind (das 0. Qubit ist am weitesten rechts): ZZII+IZZI+ZIIZ+IZIZ+IIZZZZII + IZZI + ZIIZ + IZIZ + IIZZ. Sobald der Operator konstruiert ist, kann der Ansatz für den QAOA-Algorithmus leicht mit Hilfe der QAOAAnsatz -Schaltung aus der Qiskit-Schaltungsbibliothek erstellt werden.

# 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")

Output:

Output of the previous code cell

In der vorstehenden Abbildung ist der Ansatz zur Verdeutlichung in einfachen Gattern dargestellt. Sie kann jedoch in mehreren Zerlegungsstufen ausgedrückt werden, indem man das Argument reps ändert oder die Schaltung ohne die Zerlegungsmethode zeichnet. Die folgende Darstellung zeigt zum Beispiel direkt die QAOA-Struktur mit dem Standardwert für die Wiederholungen, der reps=1 lautet.

ansatz.decompose(reps=2).draw("mpl")

Output:

Output of the previous code cell

Quantum Machine Learning

Beim maschinellen Lernen ist eine häufige Anwendung die Klassifizierung von Daten in zwei oder mehr Kategorien. Dabei wird ein Datenpunkt in eine Merkmalskarte kodiert, die klassische Merkmalsvektoren auf den Quanten-Hilbert-Raum abbildet. Die Konstruktion von Quantenmerkmalen auf der Grundlage parametrisierter Quantenschaltungen, die klassisch nur schwer zu simulieren sind, ist ein wichtiger Schritt zur Erlangung eines potenziellen Vorteils gegenüber klassischen Ansätzen des maschinellen Lernens und ein aktiver Bereich der aktuellen Forschung.

Die zz_feature_map kann zur Erstellung einer parametrisierten Schaltung verwendet werden. Wir können unsere Datenpunkte an die Feature-Map übergeben ( xx ) und eine separate Variationsform zur Übergabe von Gewichten als Parameter ( θ\theta ).

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")

Output:

Output of the previous code cell

Zusammenfassung

In dieser Lektion haben Sie gelernt, wie Sie Ihren Suchraum mit einer Variationsform definieren können:

  • Vorbereitung von Zuständen mit einer parametrisierten Quantenschaltung, bei der Gatter mit abstimmbaren Parametern definiert sind
  • Wie man Ansaetze konstruiert, die einen Kompromiss zwischen Geschwindigkeit und Genauigkeit darstellen
  • Heuristische Ansaetze
  • Problemspezifische Ansaetze

Unser High-Level-Variations-Workload sieht wie folgt aus:

Ein Schaltplan mit zwei Einheiten: eine zur Vorbereitung des Referenzzustands und eine andere zur Vorbereitung des Ansatzes.

Für jeden Variationsparameter θ⃗\vec\theta wird ein anderer Quantenzustand erzeugt. Um die optimalen Parameter zu finden, müssen wir eine problemspezifische Kostenfunktion definieren, um die Parameter unseres Ansatzes iterativ zu aktualisieren.

War diese Seite hilfreich?
Melden Sie auf GitHub einen Fehler, einen Tippfehler oder fordern Sie Inhalte an.