Skip to main content
IBM Quantum Platform

Dynamische Schaltkreise ausführen

Dynamische Schaltkreise sind leistungsstarke Werkzeuge, mit denen man Qubits während der Ausführung eines Quantenschaltkreises messen und anschließend auf der Grundlage der Ergebnisse dieser Messungen innerhalb des Schaltkreises klassische Logikoperationen durchführen kann. Dieser Prozess wird auch als klassisches Feedforward bezeichnet. Auch wenn wir erst am Anfang stehen, was das Verständnis dafür angeht, wie dynamische Schaltkreise am besten genutzt werden können, hat die Quantenforschungsgemeinschaft bereits eine Reihe von Anwendungsfällen identifiziert, darunter die folgenden:

Diese durch dynamische Schaltungen erzielten Verbesserungen sind jedoch mit Kompromissen verbunden. Messungen während des Schaltablaufs und klassische Operationen haben in der Regel eine längere Ausführungszeit als Zwei-Qubit-Gatter, und dieser Zeitaufwand könnte die Vorteile einer geringeren Schaltungstiefe zunichte machen. Daher ist die Verkürzung der Messdauer bei Messungen in der Mitte des Schaltkreises ein Schwerpunkt bei den Verbesserungen, die „ IBM Quantum® “ mit der Veröffentlichung der neuen Version der dynamischen Schaltkreise vornimmt. Weitere Einschränkungen bei der Verwendung dynamischer Schaltkreise finden Sie in der Kompatibilitätstabelle für die Funktionen „Estimator“ und „Sampler “.

Die Spezifikation „ OpenQASM. 3“ definiert eine Reihe von Kontrollflussstrukturen, doch der „ IBM Quantum Compute Service“ unterstützt derzeit nur die bedingte Anweisung if . In „ Qiskit SDK “ entspricht dies der Methode „if_test“ unter QuantumCircuit. Diese Methode gibt einen Kontextmanager zurück und wird in der Regel in einer -Anweisung with verwendet. In dieser Anleitung wird beschrieben, wie diese bedingte Anweisung verwendet wird.

Note

Die Code-Beispiele in diesem Leitfaden verwenden den Standard-Messbefehl für Messungen während des Betriebs. Es wird jedoch empfohlen, stattdessen die MidCircuitMeasure Anweisung zu verwenden, sofern das Backend dies unterstützt. Weitere Informationen finden Sie im Abschnitt „Messungen in der Mitte des Schaltkreises “.

  • Der Code auf dieser Seite wurde unter Berücksichtigung der folgenden Anforderungen entwickelt. Wir empfehlen, diese Versionen oder neuere zu verwenden.

    qiskit[all]~=2.5.2
    qiskit-ibm-runtime~=0.47.0
    

Finde Backends, die dynamische Schaltkreise unterstützen

Um alle Backends zu ermitteln, auf die Ihr Konto zugreifen kann und die dynamische Verbindungen unterstützen, führen Sie einen Code wie den folgenden aus. In diesem Beispiel wird davon ausgegangen, dass Sie Ihre Anmeldedaten gespeichert haben. Sie können die Anmeldedaten auch explizit angeben, wenn Sie Ihr „ IBM Quantum Compute Service“-Konto initialisieren. Auf diese Weise könnten Sie beispielsweise die auf einer bestimmten Instanz oder für einen bestimmten Tariftyp verfügbaren Backends anzeigen.

Hinweise
  • Welche Backends für das Konto verfügbar sind, hängt von der in den Anmeldedaten angegebenen Instanz ab.
  • Die neue Version von „Dynamic Circuits“ steht nun allen Nutzern auf allen Backends zur Verfügung. Weitere Einzelheiten finden Sie in der Ankündigung.
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
dc_backends = service.backends(dynamic_circuits=True)
print(dc_backends)

Output:

[<IBMBackend('ibm_pittsburgh')>, <IBMBackend('ibm_boston')>, <IBMBackend('ibm_fez')>, <IBMBackend('ibm_marrakesh')>, <IBMBackend('ibm_kingston')>]

Messungen während des Betriebs

Vor der Einführung von „ qiskit-ibm-runtimev0.43.0 “ measure war dies die einzige Messanweisung in Qiskit. Messungen in der Mitte eines Stromkreises stellen jedoch andere Anforderungen an die Abstimmung als Messungen an den Anschlüssen (Messungen, die am Ende eines Stromkreises erfolgen). Beispielsweise müssen Sie bei der Optimierung einer Messung während der Befehlsausführung die Befehlsdauer berücksichtigen, da längere Befehle zu störungsanfälligeren Schaltungen führen. Bei Endmessungen müssen Sie die Befehlsdauer nicht berücksichtigen, da nach den Endmessungen keine Befehle mehr folgen.

Note

Der MidCircuitMeasure Befehl entspricht dem measure_2 Befehl, der in der. supported_instructions-Datei des Backends angegeben ist. Allerdings wird nicht von allen measure_2 Backends unterstützt. Verwenden Sie service.backends(filters=lambda b: "measure_2" in b.supported_instructions) , um Backends zu finden, die dies unterstützen. Möglicherweise werden in Zukunft weitere Messungen hinzugefügt, dies kann jedoch nicht garantiert werden.

MidCircuitMeasure-Methode

In qiskit-ibm-runtime v0.43.0 wurde die MidCircuitMeasure Anleitung veröffentlicht. Wie der Name schon sagt, handelt es sich um einen neuen Befehl, der für die Verarbeitung in der Mitte des Schaltkreises auf QPUs v IBM® s optimiert ist. Zwar können Sie für eine Messung in der Mitte QuantumCircuit.measure des Stromkreises verwenden, doch aufgrund seiner Bauweise ist in der Regel die MidCircuitMeasure bessere Wahl. Beispielsweise verursacht dies weniger Overhead in Ihrer Schaltung als bei der Verwendung von QuantumCircuit.measure.

from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime.circuit import MidCircuitMeasure

service = QiskitRuntimeService()
backend = service.least_busy(
    operational=True, simulator=False, dynamic_circuits=True
)

circ = QuantumCircuit(2, 2)
circ.x(0)
circ.append(MidCircuitMeasure(), [0], [0])
# circ.measure([0], [0])
# circ.measure_all()
print(circ.draw(cregbundle=False))

Output:

     ┌───┐┌────────────┐
q_0: ┤ X ├┤0           ├
     └───┘│            │
q_1: ─────┤  Measure_2 ├
          │            │
c_0: ═════╡0           ╞
          └────────────┘
c_1: ═══════════════════
                        
Wichtige Hinweise
  • Es muss mindestens ein klassisches Register vorhanden sein, um Messungen nutzen zu können.
  • Für die Sampler-Primitive sind Schaltungsmessungen erforderlich. Mit dem Element „Estimator“ können Sie Schaltungsmessungen hinzufügen, diese werden jedoch ignoriert.

Store

Ab qiskit-ibm-runtime Version 0.47.0 können Sie den store Befehl verwenden, um das Ergebnis eines klassischen Ausdrucks zu speichern, falls dieser Ausdruck wiederholt verwendet werden soll. Operationen werden automatisch parallelisiert, wodurch Ihr Code zur Laufzeit deutlich effizienter wird.

Weitere Informationen finden Sie im Leitfaden zu klassischem Feedforward und Kontrollfluss.

Note

Wenn Sie verwenden store , um einen Wert in einem klassischen Register auf einem realen Backend zu speichern, wird dieser Wert lediglich während der Ausführung im Speicher abgelegt und nicht kopiert oder im Ergebnis des Jobs zurückgegeben.

if_test Im folgenden Code hat beispielsweise während der Ausführung denselben Wert wie creg , temp und funktioniert wie erwartet. Nachdem der Job jedoch abgeschlossen ist, enthält die temp im Job-Ergebnis zurückgegebene BitArray nicht den Wert von creg. Das heißt, job.result()[0].data.temp ist 0.

creg = ClassicalRegister(3, "c")
temp = ClassicalRegister(3, "temp")
...
qc.store(temp, creg)
with circuit.if_test((temp, 0b001)):
    ...

Vollständiges Beispiel

Der folgende Code erstellt eine dynamische Schaltung und führt sie auf der Hardware „ IBM® “ aus.

from qiskit_ibm_runtime import SamplerV2, QiskitRuntimeService
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.transpiler import generate_preset_pass_manager

service = QiskitRuntimeService()
backend = service.least_busy(
    operational=True, simulator=False, dynamic_circuits=True
)

# Create a dynamic circuit

qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
qc = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits

qc.h(q0)
qc.measure(q0, c0)
with qc.if_test((c0, 1)):
    qc.x(q0)
qc.measure(q0, c0)


# Convert to an ISA circuit for the given backend

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)

# Generate samplers for backend targets
sampler = SamplerV2(backend)

# Submit jobs
sampler_job = sampler.run([isa_circuit])
result = sampler_job.result()

print(
    f">>> {' Job ID:':<10}  {sampler_job.job_id()} ({sampler_job.status()})"
)

Output:

>>>  Job ID:    dab7lcbvpcac73ddek2g (DONE)

Einschränkungen bei Quantencomputern

Beachten Sie die folgenden Einschränkungen, wenn Sie dynamische Schaltkreise in Quantum Compute ausführen.

  • Aufgrund des begrenzten physischen Speichers in der Steuerelektronik gibt es auch eine Begrenzung hinsichtlich der Anzahl der if Anweisungen und der Größe ihrer Operanden. Diese Obergrenze hängt von der Anzahl der Übertragungen und der Anzahl der übertragenen Bits in einem Auftrag (nicht in einer Verbindung) ab.

    Bei der Verarbeitung einer if Bedingung müssen Messdaten an die Steuerlogik übertragen werden, damit diese die Auswertung vornehmen kann. Eine Übertragung ist die Übertragung eindeutiger klassischer Daten, und die Anzahl der übertragenen Bits entspricht der Anzahl der übertragenen klassischen Bits. Beachten Sie Folgendes:

    c0 = ClassicalRegister(3)
    c1 = ClassicalRegister(5)
    ...
    with circuit.if_test((c0, 1)) ...
    with circuit.if_test((c0, 3)) ...
    with circuit.if_test((c1[2], 1)) ...

    Im vorangegangenen Code-Beispiel werden die ersten beiden if_test Objekte in c0 als eine einzige Übertragung betrachtet, da sich der Inhalt c0 von nicht geändert hat und daher nicht erneut übertragen werden muss. Die Sendung if_test um c1 ist eine Wiederholung. Der erste sendet alle drei Bits, der zweite c0 sendet nur ein Bit, sodass insgesamt vier Bits gesendet werden.

    Wenn Sie derzeit jeweils 60 Bits übertragen, kann der Auftrag etwa 300 Übertragungen umfassen. Wenn Sie jedoch jedes Mal nur ein Bit senden, kann der Auftrag 2400 Sendungen umfassen.

  • Der in einer if_test -Anweisung verwendete Operand darf höchstens 32 Bit lang sein. Wenn Sie also einen ganzen Wert vergleichen ClassicalRegister, darf ClassicalRegister dessen Größe höchstens 32 Bit betragen. Wenn Sie jedoch nur ein einzelnes Bit aus a vergleichen ClassicalRegister, kann ClassicalRegister dieses beliebig groß sein (da der Operand nur aus einem Bit besteht).

    Beispielsweise funktioniert der Code-Block „Nicht gültig“ nicht, da mehr cr als 32 Bit umfasst. Sie können jedoch ein klassisches Register verwenden, das breiter als 32 Bit ist, wenn Sie nur ein Bit testen, wie im Code-Block „Valid“ gezeigt.

       cr = ClassicalRegister(50)
       qr = QuantumRegister(50)
       circuit = QuantumCircuit(qr, cr)
       ...
       circ.measure(qr, cr)
       with circ.if_test((cr, 15)):
          ...
  • Verschachtelte Bedingungen sind nicht zulässig. Der folgende Code-Block funktioniert beispielsweise nicht, da er ein if_test innerhalb eines anderen enthält if_test:

       c1 = ClassicalRegister(1, "c1")
       c2 = ClassicalRegister(2, "c2")
       ...
       with circ.if_test((c1, 1)):
        with circ.if_test(c2, 1)):
         ...
  • Die Verwendung von reset oder Messwerten innerhalb von Bedingungen wird nicht unterstützt.

  • Arithmetische Operationen werden nicht unterstützt.

  • In der Funktionstabelle zu „ OpenQASM “ 3 können Sie nachsehen, welche Funktionen von „ OpenQASM “ 3 von Qiskit und Quantum Compute unterstützt werden.

  • Wenn „ OpenQASM “ 3 (anstelle von QuantumCircuit) als Eingabeformat verwendet wird, um Schaltungen an „ IBM Quantum “-Primitive zu übergeben, werden nur Anweisungen unterstützt, die in Qiskit geladen werden können. Klassische Operationen werden beispielsweise nicht unterstützt, da sie nicht in Qiskit geladen werden können. Weitere Informationen finden Sie unter „Importieren eines Programms aus ‚ OpenQASM ‘ 3 in Qiskit “.

  • Die forBefehle switch , while, und werden nicht unterstützt.


Verwenden Sie dynamische Schaltkreise mit Estimator

Da Estimator keine dynamischen Schaltungen unterstützt, kannst du stattdessen Sampler verwenden und deine eigenen Messschaltungen erstellen.

Um das Verhalten von Estimator nachzubilden, gehen Sie wie folgt vor:

  1. Fassen Sie die Terme aller Observablen zu einer Partition zusammen. Dies kann beispielsweise mithilfe von PauliList API… erfolgen.
    Note

    Mit dem Attribut BitArray „primitive“ können Sie die Erwartungswerte der angegebenen Observablen berechnen.

  2. Führen Sie pro Partition einen Basiswechsel-Durchlauf durch (je nachdem, welcher Basiswechsel für die jeweilige Partition erforderlich ist). Weitere Informationen finden Sie im measurement_bases Zusatzmodul „Measurement bases“. Weitere Informationen finden Sie in der Dokumentation zum Qiskit-Addon-Utilities-Paket.
  3. Addiere die Ergebnisse für jede Partition wieder zusammen.

Einschränkungen

Sehen Sie sich die Kompatibilitätsübersicht für die Funktionen an, um sich über die Einschränkungen bei der Verwendung dynamischer Schaltkreise zu informieren. Beachten Sie, dass die Kompatibilität der Funktionen nicht von den Primitiven abhängt.


Nächste Schritte

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