Skip to main content
IBM Quantum Platform

Approximativer Quantencompiler

qiskit.synthesis.unitary.aqc

Implementierung des approximativen Quantencompilers, wie in der Abhandlung [1] beschrieben.


Schnittstelle

Die öffentliche Hauptschnittstelle dieses Moduls erreicht man, indem man unitary_synthesis_method='aqc' an transpile(). Dadurch wird die Synthesemethode auf AQCSynthesisPlugin umgestellt. Die einzelnen Klassen sind:

Kolumne „ 1 “
Kolumne „ 2 “
AQC( [Optimierer, Startwert] )Eine generische Implementierung des Approximate Quantum Compilers.
ApproximateCircuit(Anzahl_Qubits[, Name] )Eine Basisklasse, die eine ungefähre Schaltung darstellt.
ApproximatingObjective()Eine Basisklasse für die Definition eines Optimierungsproblems.
CNOTUnitCircuit(num_qubits, cnots[, tol, name] )Eine Klasse, die eine ungefähre Schaltung auf der Grundlage von CNOT-Einheitsblöcken darstellt.
CNOTUnitObjective(num_qubits, cnots)Eine Basisklasse für eine Problemdefinition auf der Grundlage der CNOT-Einheit.
DefaultCNOTUnitObjective(num_qubits, cnots)Eine naive Umsetzung der Zielfunktion auf der Grundlage von CNOT-Einheiten.
FastCNOTUnitObjective(num_qubits, cnots)Implementierung einer Zielfunktion und eines Gradientenrechners, der ähnlich wie DefaultCNOTUnitObjective ist, aber um ein Vielfaches schneller.

Mathematische Details

Wir interessieren uns für die Kompilierung einer Quantenschaltung, die wir als Suche nach der besten Schaltungsrepräsentation in Form einer geordneten Gatterfolge einer unitären Zielmatrix U∈U(d)U\in U(d) mit einigen zusätzlichen Hardwarebeschränkungen formalisieren. Insbesondere betrachten wir Darstellungen, die in Bezug auf die Hardware-Konnektivität sowie die Gattertiefe eingeschränkt werden können, und wir wählen eine Gatterbasis in Form von CNOT- und Rotationsgattern. Wir erinnern daran, dass die Kombination von CNOT und Rotationstoren in SU(d)SU(d) universell ist und daher die Kompilierung nicht einschränkt.

Um genau zu definieren, was wir unter der besten Schaltungsdarstellung verstehen, definieren wir die Metrik als die Frobenius-Norm zwischen der unitären Matrix der kompilierten Schaltung VV und der Ziel-Unitar-Matrix UU, d. h. ∥V−U∥F\|V - U\|_{\mathrm{F}}. Diese Wahl ist durch Überlegungen der mathematischen Programmierung begründet und steht im Zusammenhang mit anderen Formulierungen, die in der Literatur zu finden sind. Schauen wir uns das Problem einmal genauer an.

nn sei die Anzahl der Qubits und d=2nd=2^n. Bei einer CNOT-Struktur ctct und einem Vektor von Drehwinkeln θ\theta bildet die parametrische Schaltung eine Matrix Vct(θ)∈SU(d)Vct(\theta)\in SU(d). Wenn uns eine Zielschaltung gegeben wird, die eine Matrix U∈SU(d)U\in SU(d) bildet, dann möchten wir berechnen

argmaxθ1d∣⟨Vct(θ),U⟩∣\mathrm{argmax}_{\theta}\frac{1}{d}|\langle Vct(\theta),U\rangle|

wobei das innere Produkt das innere Produkt von Frobenius ist. Beachten Sie, dass ∣⟨V,U⟩∣≤d|\langle V,U\rangle|\leq d für alle Einheiten UU und VV gilt, so dass das Ziel eine Reichweite von [0,1][0,1] hat.

Unsere Strategie ist es, Folgendes zu maximieren

1dℜ⟨Vct(θ),U⟩\frac{1}{d}\Re \langle Vct(\theta),U\rangle

unter Verwendung seiner Steigung. Wir werden nun die Einzelheiten anhand eines Beispiels erläutern.

Während der Bereich von VctVct konstruktionsbedingt eine Teilmenge von SU(d)SU(d) ist, kann die Zielschaltung eine allgemeine unitäre Matrix bilden. Für jede U∈U(d)U\in U(d),

exp⁡(2πik/d)det⁡(U)1/dU∈SU(d) for all k∈{0,…,d−1}.\frac{\exp(2\pi i k/d)}{\det(U)^{1/d}}U\in SU(d)\text{ for all }k\in\{0,\ldots,d-1\}.

Daher sollten wir die Zielschaltung durch ihre globale Phase normalisieren und dann die normalisierte Schaltung annähernd kompilieren. Wir können die globale Phase später wieder einfügen.

In dem Algorithmus bezeichnet U′U' die nicht-normierte Zielmatrix und UU die normierte Zielmatrix. Da wir nun UU haben, geben wir die Gradientenfunktion an den Optimierer der Nesterov-Methode und berechnen θ\theta.

Um die globale Phase wieder einzufügen, können wir den Steuerkreis wie folgt bilden

⟨Vct(θ),U′⟩∣⟨Vct(θ),U′⟩∣Vct(θ).\frac{\langle Vct(\theta),U'\rangle}{|\langle Vct(\theta),U'\rangle|}Vct(\theta).

Man beachte, dass wir die Nesterov-Methode in der Arbeit zwar optimiert haben, aber nur wegen ihrer Konvergenzgarantien, nicht wegen ihrer Geschwindigkeit in der Praxis. Es ist viel schneller, L-BFGS zu verwenden, das in dieser Implementierung als Standardoptimierer eingesetzt wird.

Eine grundlegende Anwendung des AQC-Algorithmus sollte die folgenden Schritte umfassen:

# Define a target circuit as a unitary matrix
unitary = ...

# Define a number of qubits for the algorithm, at least 3 qubits
num_qubits = round(math.log2(unitary.shape[0]))

# Choose a layout of the CNOT structure for the approximate circuit, e.g. ``spin`` for
# a linear layout.
layout = options.get("layout") or "spin"

# Choose a connectivity type, e.g. ``full`` for full connectivity between qubits.
connectivity = options.get("connectivity") or "full"

# Define a targeted depth of the approximate circuit in the number of CNOT units.
depth = int(options.get("depth") or 0)

# Generate a network made of CNOT units
cnots = make_cnot_network(
    num_qubits=num_qubits,
    network_layout=layout,
    connectivity_type=connectivity,
    depth=depth
)

# Create an optimizer to be used by AQC
optimizer = partial(scipy.optimize.minimize, method="L-BFGS-B")

# Create an instance
aqc = AQC(optimizer)

# Create a template circuit that will approximate our target circuit
approximate_circuit = CNOTUnitCircuit(num_qubits=num_qubits, cnots=cnots)

# Create an objective that defines our optimization problem
approximating_objective = DefaultCNOTUnitObjective(num_qubits=num_qubits, cnots=cnots)

# Run optimization process to compile the unitary
aqc.compile_unitary(
    target_matrix=unitary,
    approximate_circuit=approximate_circuit,
    approximating_objective=approximating_objective
)

Nun ist approximate_circuit eine Schaltung, die die Zielunitarität bis zu einem gewissen Grad annähert und anstelle der ursprünglichen Matrix verwendet werden kann.

Dazu wird eine Hilfsfunktion verwendet, make_cnot_network.

make_cnot_network

qiskit.synthesis.unitary.aqc.make_cnot_network(num_qubits, network_layout='spin', connectivity_type='full', depth=0)

GitHub

Erzeugt ein Netzwerk, das aus Bausteinen besteht, die jeweils ein CNOT-Gatter und möglicherweise einige Ein-Qubit-Gatter enthalten. Dieses Netz modelliert einen fraglichen Quantenoperator. Man beachte, dass jeder Baustein 2 Eingänge und Ausgänge hat, die einem Qubit-Paar entsprechen. Was wir hier tatsächlich zurückgeben, ist eine Kette von Indizes von Qubit-Paaren, die von jedem Baustein in einer Reihe gemeinsam genutzt werden.

Parameter

  • num_qubits (int) – anzahl der Qubits.
  • network_layout (str) – art der Netzgeometrie, {"sequ", "spin", "cart", "cyclic_spin", "cyclic_line"}.
  • connectivity_type (str) – art der Inter-Qubit-Konnektivität, {"full", "line", "star"}.
  • depth (int) – tiefe des CNOT-Netzes, d. h. die Anzahl der Schichten, wobei jede Schicht aus einem einzelnen CNOT-Block besteht; der Standardwert wird gewählt, wenn L <= 0.

Rückgabe

Eine Matrix der Größe (2, N) Matrix, die die Schichten im cnot-Netz definiert, wobei N

ist entweder gleich L oder durch einen konkreten Typ des Netzes definiert.

Erhöht

ValueError - wenn ein nicht unterstützter Typ des CNOT-Netz-Layouts oder eine nicht unterstützte Anzahl von Qubits oder eine nicht unterstützte Kombination von Parametern übergeben wird.

Rückgabetyp

ndarray

Man kann die Vorteile einer beschleunigten Version der Zielfunktion nutzen. Er implementiert denselben mathematischen Algorithmus wie der Standardalgorithmus DefaultCNOTUnitObjective , läuft aber um ein Vielfaches schneller. Die Instanziierung der beschleunigten Zielfunktionsklasse ist ähnlich wie im Standardfall:

# Erstellen eines Ziels, das unser Optimierungsproblem definiert approximating_objective = FastCNOTUnitObjective(num_qubits=num_qubits, cnots=cnots)

Der Rest des Codes im obigen Beispiel ändert sich nicht.

Referenzen

[1] : Liam Madden, Andrea Simonetto, Best Approximate Quantum Compiling Problems.

arXiv:2106.05649

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