Beispiele für Testamentsvollstrecker
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 samplomatic~=0.21.0
Die Beispiele in diesem Abschnitt veranschaulichen einige gängige Anwendungsmöglichkeiten der Executor-Primitive. Bevor Sie diese Beispiele ausführen, befolgen Sie bitte die Anweisungen unter „Qiskit und Executor installieren – Schnellstart “.
Vorbereitende Schritte
Einige der Code-Beispiele auf dieser Seite verwenden samplex, das zum Samplomatic-Paket gehört. Bevor Sie diese Code-Blöcke ausführen, müssen Sie daher Samplomatic installieren, wie im folgenden Code-Block gezeigt. Weitere Informationen finden Sie in der Samplomatic-Dokumentation.
pip install samplomatic
# For visualization support, include the visualization dependencies.
# pip install samplomatic[vis]Beispiel: Parametrisierte Schaltung
Dieses Beispiel zeigt, wie man Schaltkreiselemente mit Parametern sowie Samplex-Elemente hinzufügt. Es umfasst folgende Schritte:
- Schaltung einrichten: Erstellen und transpilieren Sie die Zielschaltung.
- Erstellen Sie ein Samplex: Gruppieren Sie Gatter und Messungen in beschrifteten Feldern und generieren Sie die Schaltungsvorlage sowie das Samplex-Paar.
- Ausführen: Fügen Sie ein Schaltkreis-Element und ein Samplex-Element zu einem
QuantumProgramJob hinzu und führen Sie beide in einem einzigen Job aus.
Schalte den Schaltkreis zusammen
Bereite einen GHZ-Zustand mit drei Qubits vor, drehe die Qubits um die Pauli-Z-Achse und miss die Qubits in der Rechenbasis.
from qiskit.circuit import Parameter, QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService, Executor
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from qiskit.transpiler import generate_preset_pass_manager
import numpy as np
from samplomatic import build
from samplomatic.transpiler import generate_boxing_pass_manager
# Generate the circuit
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.h(1)
circuit.cz(0, 1)
circuit.h(1)
circuit.h(2)
circuit.cz(1, 2)
circuit.h(2)
circuit.rz(Parameter("theta"), 0)
circuit.rz(Parameter("phi"), 1)
circuit.rz(Parameter("lam"), 2)
circuit.measure_all()Geben Sie das Backend an und transpilieren Sie die Schaltung so, dass ausschließlich von der QPU unterstützte Befehle verwendet werden (sogenannte ISA-Schaltung).
# Initialize the service and choose a backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# Transpile the circuit to ISA
preset_pass_manager = generate_preset_pass_manager(
backend=backend, optimization_level=3
)
isa_circuit = preset_pass_manager.run(circuit)Bereiten Sie den Samplex vor
Verwenden Sie die generate_boxing_pass_manager Komfortfunktion und ihre Twirling-Parameter, um Zwei-Qubit-Gatter und Messungen in Boxen zu gruppieren und Twirling-Annotationen hinzuzufügen.
boxing_pm = generate_boxing_pass_manager(
# Add gate twirling
enable_gates=True,
# Add measurement twirling
enable_measures=True,
)
boxed_circuit = boxing_pm.run(isa_circuit)Verwenden Sie die build Methode, um die Schaltungsvorlage und das Samplex zu generieren.
# Build the template circuit and the samplex
template_circuit, samplex = build(boxed_circuit)Führen Sie die Zirkeltrainings durch
Der Executor führt QuantumProgram Objekte aus. Jedes QuantumProgram kann mehrere Elemente enthalten. In diesem Beispiel werden ein Schaltkreis-Element und ein Samplex-Element zur Ausführung hinzugefügt. Ausführliche Informationen finden Sie unter „Executor-Ein- und -Ausgabe “.
Der erste Schritt besteht darin, ein leeres Programm zu initialisieren, das für jede Konfiguration jedes Elements Aufnahmen anfordert 1024 .
# Generate a quantum program
program = QuantumProgram(shots=1024)Füge das Schaltkreiselement an das QuantumProgram. an. Dieser Schaltungsartikel besteht aus zwei Teilen – der ISA-Schaltung und 10 Sätzen ihrer Parameterwerte.
# Append the circuit and the parameter values to the program
program.append_circuit_item(
isa_circuit,
circuit_arguments=np.random.rand(10, 3), # 10 sets of parameter values
)Füge das Samplex-Element mit diesen Argumenten an das QuantumProgram an:
- Die Schaltungsvorlage und der von der
buildFunktion erzeugte Samplex - Zehn Sätze von Parameterwerten für die ursprüngliche Schaltung
- Die Anzahl der durchzuführenden Randomisierungen
# Append the template circuit and samplex as a samplex item
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"parameter_values": np.random.rand(
10, 3
), # 10 sets of parameter values
},
shape=(2, 14, 10),
)Executor-Job ausführen
# initialize an Executor with default options
executor = Executor(mode=backend)
# Submit the job
job = executor.run(program)
# Retrieve the result
result = job.result()Rufe das Ergebnis für jede Aufgabe ab.
# Access the results of the classical register of task #0, the CircuitItem
result_0 = result[0]["meas"]
# Access the results of the classical register of task #1, the SamplexItem
result_1 = result[1]["meas"]Beispiel: PEC durchführen
Dieses Beispiel zeigt, wie man mit einem Samplex-Element eine probabilistische Fehlerkompensation ( PEC ) zur Fehlerminderung durchführt.
Betrachten wir eine gespiegelte Version einer Schaltung mit zehn Qubits und zwei unterschiedlichen Schichten von CX-Gattern. Dies sind die wichtigsten Aufgaben:
- Führe die Übung mit Drehbewegungen aus.
- Führen Sie die Schaltung mit PEC-Kompensation aus, wie in der Veröffentlichung „Probabilistic error cancellation with sparse Pauli-Lindblad models on noisy quantum processors“ beschrieben.
Die Pipeline umfasst folgende Schritte:
- Vorgehensweise: Erstellen Sie die Zielschaltung und fassen Sie deren Operationen in Blöcken zusammen.
- Lernen: Ermitteln Sie das Rauschen der Befehle, das wir mit PEC unterdrücken wollen.
- Ausführen: Den Schaltkreis auf einem Backend ausführen.
- Auswerten: Die Ergebnisse nachbearbeiten und auswerten.
Zum Vergleich werden wir diese gespiegelte Schaltung zweimal ausführen. Einmal nur mit Pauli-Twist und einmal mit PEC-Minderung.
Die Ausführungszeit für dieses Beispiel beträgt auf einem Heron-Prozessor ( r2 ) etwa 10 Minuten.
Schalte den Schaltkreis zusammen
Wählen Sie ein Backend aus und erstellen Sie eine Schaltung mit 10 Qubits.
from qiskit_ibm_runtime import QiskitRuntimeService, Executor
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.transpiler import generate_preset_pass_manager
from samplomatic.transpiler import generate_boxing_pass_manager
from samplomatic import build
# Initialize the service and choose a backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# Prepare a circuit
num_qubits = 10
num_layers = 10
qubits = list(range(num_qubits))
circuit = QuantumCircuit(num_qubits)
for layer_idx in range(num_layers):
circuit.rx(Parameter(f"theta_{layer_idx}"), qubits)
for i in range(num_qubits // 2):
circuit.cz(qubits[2 * i], qubits[2 * i + 1])
circuit.rx(Parameter(f"phi_{layer_idx}"), qubits)
for i in range(num_qubits // 2 - 1):
circuit.cz(qubits[2 * i] + 1, qubits[2 * i + 1] + 1)
circuit.draw("mpl", scale=0.35, fold=100)Output:
Kombiniere die Schaltung mit ihrer Umkehrschaltung, um eine Spiegelschaltung zu bilden.
mirror_circuit = circuit.compose(circuit.inverse())
mirror_circuit.measure_all()
mirror_circuit.draw("mpl", scale=0.35, fold=100)Output:
Lege einige Parameterwerte fest:
import numpy as np
parameter_values = np.random.rand(mirror_circuit.num_parameters)Verwenden Sie den Pass-Manager, um die Schaltung in eine ISA-Schaltung zu transpilieren.
preset_pass_manager = generate_preset_pass_manager(
backend=backend,
optimization_level=3,
)
isa_circuit = preset_pass_manager.run(mirror_circuit)Gruppieren Sie anschließend die Gatter und Messungen in beschrifteten Feldern. Sie können dies manuell tun oder der Einfachheit halber die generate_boxing_pass_manager Funktion von Samplomatic verwenden. Auf den ersten Schaltkreis wird lediglich eine Drehung angewendet, daher ist lediglich die Twirl Anmerkung erforderlich. Der zweite Durchlauf wird mit vollständiger PEC-Abmilderung durchgeführt und erfordert sowohl Twirl als auch InjectNoise Anmerkungen.
# Pass manager used to create twirled-annotated boxes.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=True,
)
mirror_circuit_twirl = boxing_pm.run(isa_circuit)
# Pass manager used to create a new boxed circuit with
# both Twirl and InjectNoise annotations.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=True,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)
mirror_circuit_pec = boxing_pm.run(isa_circuit)Lerne den Klang kennen
InjectNoiseUm die Anzahl der Experimente zum Rauschlernen zu minimieren, identifizieren Sie die eindeutigen Anweisungen im zweiten Schaltkreis (dem mit den mit gekennzeichneten Kästchen). Bei der Definition der Eindeutigkeit gelten zwei Box-Anweisungen als gleich, wenn beide der folgenden Bedingungen erfüllt sind:
- Ihr Inhalt ist identisch, bis hin zu Einzelqubit-Gattern.
- Ihre
TwirlAnmerkung ist identisch (alle anderen Anmerkungen werden ignoriert).
Daraus ergeben sich drei spezifische Anweisungen, nämlich die Boxen für ungerade und gerade Werte sowie die Box für die abschließende Messung.
from samplomatic.utils import find_unique_box_instructions
unique_box_instructions = find_unique_box_instructions(
mirror_circuit_pec.data
)
assert len(unique_box_instructions) == 3NoiseLearnerV3Initialisieren Sie ein Modell, wählen Sie die Lernparameter durch Einstellen der entsprechenden Optionen aus und führen Sie einen Lernvorgang für Rauschdaten durch.
from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3
learner = NoiseLearnerV3(backend)
learner.options.shots_per_randomization = 128
learner.options.num_randomizations = 32
learner.options.layer_pair_depths = [0, 1, 2, 4, 16, 32]
learner_job = learner.run(unique_box_instructions)
learner_job.job_id()
learner_result = learner_job.result()Konvertieren result Sie das Objekt mithilfe der result.to_dict Methode in das vom Samplex benötigte Format.
noise_maps = learner_result.to_dict(
instructions=unique_box_instructions, require_refs=False
)Führen Sie die Zirkeltrainings durch
Executor führt QuantumProgram Objekte aus. Jedes QuantumProgram kann mehrere Elemente enthalten, die dem Programm angehängt werden. Jeder Eintrag stellt eine Aufgabe dar, die das Programm ausführen soll.
Starte ein leeres Programm, das für jede Konfiguration jedes Elements Aufnahmen anfordert 1000 .
from qiskit_ibm_runtime.quantum_program import QuantumProgram
# Initialize an empty QuantumProgram
program = QuantumProgram(shots=1000)Erstelle als Nächstes die Schaltungsvorlage und den Samplex für mirror_circuit_twirl und füge sie dem Programm hinzu. Fordere 900 außerdem Zufallsauswahlen aus dem Samplex an. Das bedeutet, dass der Samplex Parametersätze generiert 900 und jeder Satz Mal (die Anzahl der Durchläufe) in der QPU ausgeführt 1000 wird.
Dies ist die erste Aufgabe des Programms (Ergebnis 0).
template_twirl, samplex_twirl = build(mirror_circuit_twirl)
program.append_samplex_item(
template_twirl,
samplex=samplex_twirl,
samplex_arguments={"parameter_values": parameter_values},
shape=(900,),
)mirror_circuit_pecFüge ebenfalls die für erstellte Schaltungsvorlage und den Samplex hinzu und fordere 900 dabei Randomisierungen an. Dies ist die zweite Aufgabe des Programms (Ergebnis 1).
template_pec, samplex_pec = build(mirror_circuit_pec)
program.append_samplex_item(
template_pec,
samplex=samplex_pec,
samplex_arguments={
"parameter_values": parameter_values,
"pauli_lindblad_maps": noise_maps,
"noise_scales": {
ref: -1.0 for ref in noise_maps
}, # Set the scales to -1 for PEC
},
shape=(900,),
)Einen Auftrag importieren Executor und übermitteln.
from qiskit_ibm_runtime.executor import Executor
executor = Executor(backend)
executor_job = executor.run(program)
executor_job.job_id()
executor_results = executor_job.result()
executor_results
twirl_result = executor_results[0]
print(f"Twirl result keys:\n {list(twirl_result.keys())}\n")
print(f"Shape of results: {twirl_result['meas'].shape}")
pec_result = executor_results[1]
print(f"PEC result keys:\n {list(pec_result.keys())}\n")
print(f"Shape of results: {pec_result['meas'].shape}")Output:
Twirl result keys:
['meas', 'measurement_flips.meas']
Shape of results: (900, 1000, 10)
PEC result keys:
['meas', 'measurement_flips.meas', 'pauli_signs']
Shape of results: (900, 1000, 10)
Ergebnisse analysieren
Schließlich werden die Ergebnisse nachbearbeitet, um die Erwartungswerte der auf jedes der zehn aktiven Qubits wirkenden Pauli-Z-Operatoren für einzelne Qubits zu schätzen (Erwartungswert: 1.0).
# Undo measurement twirling
twirl_result_unflipped = (
twirl_result["meas"] ^ twirl_result["measurement_flips.meas"]
)
# Calculate the expectation values of single-qubit Z operators
exp_vals = 1 - 2 * twirl_result_unflipped.mean(axis=1).mean(axis=0)
for qubit, val in enumerate(exp_vals):
print(f"Qubit {qubit} -> {np.round(val, 2)}")Output:
Qubit 0 -> 0.71
Qubit 1 -> 0.72
Qubit 2 -> 0.7
Qubit 3 -> 0.68
Qubit 4 -> 0.65
Qubit 5 -> 0.64
Qubit 6 -> 0.62
Qubit 7 -> 0.66
Qubit 8 -> 0.69
Qubit 9 -> 0.75
# Undo measurement twirling
pec_result_unflipped = (
pec_result["meas"] ^ pec_result["measurement_flips.meas"]
)
# Calculate the signs for PEC mitigation
signs = np.prod((-1) ** pec_result["pauli_signs"], axis=-1)
signs = signs.reshape((signs.shape[0], 1))
# Calculate the expectation values of single-qubit Z operators as required by
# PEC mitigation
exp_vals = 1 - (2 * pec_result_unflipped.mean(axis=1) * signs).mean(axis=0)
for qubit, val in enumerate(exp_vals):
print(f"Qubit {qubit} -> {np.round(val, 2)}")Output:
Qubit 0 -> 0.98
Qubit 1 -> 1.0
Qubit 2 -> 0.99
Qubit 3 -> 0.97
Qubit 4 -> 0.97
Qubit 5 -> 0.97
Qubit 6 -> 0.96
Qubit 7 -> 0.97
Qubit 8 -> 0.97
Qubit 9 -> 0.98
Nächste Schritte
- Sehen Sie sich die Übersicht über die Sendungen an.
- Erfahren Sie, wie Sie die Executor-Optionen nutzen können.
- Das Modell der gerichteten Ausführung verstehen.
- Lesen Sie die Samplomatic-Dokumentation durch.
- Erfahren Sie im Tutorial „Probabilistische Fehlerkorrektur mit schattierten Lichtkegeln “, wie Sie verschiedene Techniken zur Fehlerminderung kombinieren können, wenn Sie das Modell der gerichteten Ausführung verwenden.