Skip to main content
IBM Quantum Platform

Aufgeschobene Zeitauflösung durch Streckung

Die 3-Sprachspezifikation „ OpenQASM “ enthält einen stretch Typ, mit dem Sie anstelle der absoluten Zeitsteuerung die relative Zeitsteuerung von Operationen festlegen können. Die Unterstützung für stretch als Dauer für Delay Anweisungen wurde in Qiskit v2.0.0 hinzugefügt. Der konkrete Wert einer Stretch-Dauer wird zur Kompilierungszeit ermittelt, nachdem die genaue Dauer der kalibrierten Gates bekannt ist. Der Compiler versucht, die Streckungsdauer zu minimieren, vorbehaltlich zeitlicher Beschränkungen für ein oder mehrere Qubits. Anschließend können Sie Gate-Designs wie gleichmäßig beabstandete Gates (z. B. zur Implementierung einer Echoentkopplungssequenz höherer Ordnung), linksbündige Ausrichtung einer Gate-Sequenz oder die Anwendung eines Gates für die Dauer einer Teilschaltung ausdrücken, ohne das genaue Timing zu kennen.


Beispiele

Dynamische Entkopplung

Ein gängiger Anwendungsfall von stretch ist die dynamische Entkopplung eines Qubits im Leerlauf, während ein anderes Qubit bedingten Operationen unterzogen wird.

Zum Beispiel können wir stretch verwenden, um eine dynamische Entkopplungssequenz XX auf das Qubit 1 anzuwenden, und zwar für die Dauer des bedingten Blocks, der auf das Qubit 0 angewendet wird, wie im folgenden Diagramm dargestellt:

Abbildung zur Veranschaulichung der folgenden Schaltung

Die entsprechende Schaltung würde wie folgt aussehen. Es ist zu beachten, dass ein Paar von Barrieren erforderlich ist, um die Grenzen dieses relativen Timings zu definieren.

from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit.classical import expr

qubits = QuantumRegister(2)
clbits = ClassicalRegister(2)
circuit = QuantumCircuit(qubits, clbits)
(q0, q1) = qubits
(c0, c1) = clbits

# Add barriers to define the boundaries
circuit.barrier()
circuit.h(q0)
circuit.measure(q0, c0)
with circuit.if_test((c0, 1)) as else_:
    circuit.h(q0)
with else_:
    circuit.x(q0)

# Apply an XX DD sequence with stretch on qubit 1
s = circuit.add_stretch("s")
circuit.delay(s, q1)
circuit.x(q1)
circuit.delay(expr.mul(s, 2), q1)
circuit.x(q1)
circuit.delay(s, q1)
circuit.barrier()

Terminabstimmung

In diesem Beispiel wird stretch verwendet, um sicherzustellen, dass eine Folge von Gates zwischen zwei Barrieren linksbündig ist, unabhängig von ihrer tatsächlichen Dauer:

from qiskit import QuantumCircuit
from numpy import pi

qc = QuantumCircuit(5)
qc.barrier()
qc.cx(0, 1)
qc.u(pi/4, 0, pi/2, 2)
qc.cx(3, 4)

a = qc.add_stretch("a")
b = qc.add_stretch("b")
c = qc.add_stretch("c")

# Use the stretches as Delay duration.
qc.delay(a, [0, 1])
qc.delay(b, 2)
qc.delay(c, [3, 4])
qc.barrier()
Note

Bei der Verwendung stretch mit dem „ IBM Quantum Compute Service“ wird ein etwaiger Rest, der sich aus der Auflösung einer Stretch-Einstellung ergibt, zur ersten Verzögerung hinzugefügt, bei der die Stretch-Einstellung zum Einsatz kommt.

Beispiel:

a = circuit.add_stretch("a")
circuit.barrier(q0, q1)
circuit.delay(100, q0)
circuit.delay(a, q1)  # resolve to 26
circuit.x(q1)  # duration: 8
circuit.delay(a, q1)  # resolve to 25
circuit.x(q1)  # duration: 8
circuit.delay(a, q1)  # resolve to 25
circuit.x(q1)  # duration: 8
circuit.barrier(q0, q1)

Der obige Code führt zu einem Wert von 25 mit einem Rest von 1. Bei der ersten Verzögerung[a] wird der Restbetrag hinzugefügt.

Gleichung für die Streckungsauflösung: a+8+a+8+a+8=100=3∗a+24a + 8 + a + 8 + a + 8 = 100 = 3*a + 24


Stretch-Werte im „ IBM Quantum “-Berechnungsdienst anzeigen

Der tatsächliche Wert einer Stretch-Dauer wird zur Kompilierungszeit ermittelt, nachdem die Schaltung eingeplant wurde. Wenn Sie einen Sampler-Job im „ IBM Quantum “ Compute Service ausführen, können Sie die aufgelösten Stretch-Werte in den Metadaten des Job-Ergebnisses einsehen. Die Unterstützung für stretch in Quantum Compute befindet sich derzeit noch im Versuchsstadium. Daher müssen Sie zunächst eine experimentelle Option aktivieren, um den Abruf zu ermöglichen, und anschließend wie folgt direkt über die Metadaten auf die Daten zugreifen:

# Enable stretch value retrieval.
sampler.options.experimental = {
    "execution": {
        "stretch_values": True,
        "scheduler_timing": True,
    },
}

# Access the stretch values from the metadata.
job_result = job.result()
circuit_stretch_values = (
    job_result[0].metadata["compilation"]["stretch_values"]
    )

# Visualize the timing.
# Use the sliders at the bottom, the controls at the top, and the 
# legend on the side of the output to customize the view.
draw_circuit_schedule_timing(ob.result()[0].metadata['compilation']
    ['scheduler_timing']['timing'])
Note

Obwohl die Gesamtlaufzeit in den „Compilation“-Metadaten angegeben wird, handelt es sich dabei NICHT um die für die Abrechnung herangezogene Zeit (QPU-Zeit).

Die Metadatenausgabe verstehen

Die stretch_values Metadaten geben folgende Informationen zurück:

  • Name: Der Name der angewendeten Dehnung.
  • Wert: Der gewünschte Zielwert.
  • Rest: Der Rest aus der Auflösung der Dehnung, der zur ersten Verzögerung hinzugefügt wird, die die Dehnung verwendet.
  • Erweiterte Werte: Wertesätze, die den Beginn der Dehnung und deren Dauer festlegen.

Beispiel

# Define the circuit
circuit = QuantumCircuit(4)
foo = circuit.add_stretch("foo")
bar = circuit.add_stretch("bar")
circuit.barrier()
circuit.cz(0, 1)
circuit.cz(0, 1)
circuit.cz(0, 1)
circuit.cz(0, 1)

circuit.delay(foo, 2)
circuit.x(2)
# 3*foo
circuit.delay(expr.mul(3, foo), 2)
circuit.x(2)
# 2*foo
circuit.delay(expr.mul(2, foo), 2)

circuit.delay(bar, 3)
circuit.x(3)
circuit.delay(bar, 3)

circuit.measure_all()

Metadatenausgabe

 [{'name': 'bar',
  'value': 29,
  'remainder': 1,
  'expanded_values': [[1365, 30], [1404, 29]]},
 {'name': 'foo',
  'value': 8,
  'remainder': 2,
  'expanded_values': [[1365, 10], [1384, 24], [1417, 16]]}
  ]

Die für die Dauer zurückgegebenen Werte hängen vom Zielwert und dem berechneten Restbetrag ab. Beispielsweise werden für „foo“ folgende Dauerwerte zurückgegeben:

  • foo value + remainder (8+2 = 10)
  • foo value * 3 (8 x 3 = 24)
  • foo value * 2 (8 x 2 = 16)

Sie können eine Visualisierung verwenden, um das Timing besser zu verstehen und zu überprüfen.

draw_circuit_schedule_timing(job.result()[0].metadata
    ['compilation']['scheduler_timing']['timing'])

In der folgenden Abbildung entspricht basierend auf der foo Beispielausgabe den Strecken auf Qubit 2. Die erste Streckungsverzögerung, die verwendet, foo beginnt am Ende des init_play (1365). Die Stretch-Dauer beträgt 10, sodass die Verzögerung endet, wenn das x Gate startet (1365+10=1375). Die zweite und dritte Dehnung können Sie ähnlich interpretieren.

Die Ausgabe des Befehls draw_circuit_schedule_timing wird angezeigt.

Verwenden Sie die Schieberegler unten, die Steuerelemente oben (bewegen Sie den Mauszeiger über Ihr Ausgabebild, um diese anzuzeigen) und die Legende an der Seite der Ausgabe, um die Ansicht anzupassen. Bewegen Sie den Mauszeiger über das Bild, um die genauen Daten anzuzeigen.

Ausführliche Informationen finden Sie unter dem Thema „Schaltungs-Timing visualisieren “.


Einschränkungen bei Quantencomputern

Die Unterstützung für in stretch Quantum Compute befindet sich derzeit im Versuchsstadium und unterliegt folgenden Einschränkungen:

  • Höchstens eine Streckungsvariable pro Qubit zwischen den Barrieren (implizit und explizit). Ein Qubit-Set besteht aus einem oder mehreren Qubits; diese Sets müssen sich gegenseitig ausschließen.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    circuit.delay(a, (q0, q1))
    circuit.delay(b, q0)  # Invalid because 2 stretches are applied on q0
  • Das Gebiet, das von einer Reihe von Barrieren umgeben ist, wird als Barrieregebiet bezeichnet. Eine Streckungsvariable kann nicht in mehreren Sperrbereichen verwendet werden.

    # Stretch a is used in two barrier regions
    a = circuit.add_stretch("a")
    circuit.barrier((q0, q1))
    circuit.delay(a, q0)
    circuit.barrier((q0, q1))
    circuit.delay(a, q0)
    circuit.barrier((q0, q1))
    Darstellung der Ausgabe des vorherigen
    Codes: Ungültige Verwendung von „stretch“ in Barrierebereichen
  • Streckausdrücke sind auf Ausdrücke der Form X*stretch + Y beschränkt, wobei X und Y Fließkomma- oder Ganzzahlkonstanten sind.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    c = circuit.add_stretch("c")
    
    # (a /  b) * c is not supported
    circuit.delay(expr.mul(expr.div(a, b), c), q1)
  • Streckausdrücke können nur eine einzige Streckvariable enthalten.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    circuit.delay(expr.add(a, b), 0)
  • Dehnungsausdrücke können nicht in negative Verzögerungswerte aufgelöst werden. Der aktuelle Solver leitet keine Nicht-Negativitäts-Beschränkungen ab.

    from qiskit.circuit import Duration
    
    circuit.barrier((q0, q1))
    circuit.delay(20, q1)
    # The length of this barrier region is 20dt, meaning the
    # equation for solving stretch 'a' is a + 40dt = 20dt, giving a = -20dt.
    circuit.delay(expr.add(a, Duration.dt(40)), q0)
    circuit.barrier((q0, q1))
War diese Seite hilfreich?
Melden Sie auf GitHub einen Fehler, einen Tippfehler oder fordern Sie Inhalte an.