Erste Schritte mit Primitives
Die Beta-Version eines neuen Ausführungsmodells ist jetzt verfügbar. Das Directed Execution Model bietet mehr Flexibilität bei der Anpassung deines Error-Mitigation-Workflows. Weitere Informationen findest du im Leitfaden Directed execution model.
Während diese Dokumentation die Primitives von Qiskit Runtime verwendet, die die Nutzung von IBM®-Backends ermöglichen, können die Primitives mit jedem Anbieter durch Verwendung der Backend-Primitives ausgeführt werden. Zusätzlich kannst du die Referenz-Primitives verwenden, um auf einem lokalen Statevector-Simulator zu laufen. Einzelheiten findest du unter Exact simulation with Qiskit primitives.
Die Schritte in diesem Thema beschreiben, wie du Primitives einrichtest, die Optionen erkundest, die du zur Konfiguration verwenden kannst, und sie in einem Programm aufrufst.
Um die neu unterstützten Fractional Gates zu verwenden, setze use_fractional_gates=True, wenn du ein Backend von einer QiskitRuntimeService-Instanz anforderst. Zum Beispiel:
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime
service = QiskitRuntimeService()
fractional_gate_backend = service.least_busy(use_fractional_gates=True)
Beachte, dass dies eine experimentelle Funktion ist und sich in Zukunft ändern kann.
Paketversionen
Der Code auf dieser Seite wurde mit den folgenden Anforderungen entwickelt. Wir empfehlen die Verwendung dieser oder neuerer Versionen.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
Erste Schritte mit Estimator
1. Initialisiere das Konto
Da Qiskit Runtime Estimator ein verwalteter Dienst ist, musst du zunächst dein Konto initialisieren. Anschließend kannst du die QPU auswählen, die du zur Berechnung des Erwartungswerts verwenden möchtest.
Folge den Schritten im Thema Install and set up topic, wenn du noch kein Konto hast.
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
print(backend.name)
ibm_torino
2. Erstelle einen Circuit und eine Observable
Du benötigst mindestens einen Circuit und eine Observable als Eingaben für das Estimator-Primitive.
from qiskit.circuit.library import qaoa_ansatz
from qiskit.quantum_info import SparsePauliOp
entanglement = [tuple(edge) for edge in backend.coupling_map.get_edges()]
observable = SparsePauliOp.from_sparse_list(
[("ZZ", [i, j], 0.5) for i, j in entanglement],
num_qubits=backend.num_qubits,
)
circuit = qaoa_ansatz(observable, reps=2)
# the circuit is parametrized, so we will define the parameter values for execution
param_values = [0.1, 0.2, 0.3, 0.4]
print(f">>> Observable: {observable.paulis}")
>>> Observable: ['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',
'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...', ...]
Der Circuit und die Observable müssen so transformiert werden, dass sie nur Anweisungen verwenden, die von der QPU unterstützt werden (bezeichnet als Instruction Set Architecture (ISA) Circuits). Wir verwenden den Transpiler, um dies zu tun.
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
print(f">>> Circuit ops (ISA): {isa_circuit.count_ops()}")
>>> Circuit ops (ISA): OrderedDict([('rz', 3826), ('sx', 1601), ('cz', 968)])
3. Initialisiere Qiskit Runtime Estimator
Wenn du den Estimator initialisierst, verwende den Parameter mode, um den Modus anzugeben, in dem er ausgeführt werden soll. Mögliche Werte sind batch, session oder backend-Objekte für Batch-, Session- und Job-Ausführungsmodus. Weitere Informationen findest du unter Introduction to Qiskit Runtime execution modes.
from qiskit_ibm_runtime import EstimatorV2 as Estimator
estimator = Estimator(mode=backend)
4. Rufe den Estimator auf und erhalte Ergebnisse
Rufe als Nächstes die Methode run() auf, um Erwartungswerte für die Eingabe-Circuits und -Observables zu berechnen. Der Circuit, die Observable und optionale Parameterwertesätze werden als Primitive Unified Bloc (PUB)-Tupel eingegeben.
job = estimator.run([(isa_circuit, isa_observable, param_values)])
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
>>> Job ID: d5k96c4jt3vs73ds5smg
>>> Job Status: QUEUED
result = job.result()
print(f">>> {result}")
print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")
>>> PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(), dtype=float64>), stds=np.ndarray(<shape=(), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(), dtype=float64>)), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})
> Expectation value: 25.8930784649363
> Metadata: {'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}
Erste Schritte mit Sampler
1. Initialisiere das Konto
Da Qiskit Runtime Sampler ein verwalteter Dienst ist, musst du zunächst dein Konto initialisieren. Anschließend kannst du die QPU auswählen, die du zur Berechnung des Erwartungswerts verwenden möchtest.
Folge den Schritten im Thema Install and set up topic, wenn du noch kein Konto eingerichtet hast.
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
2. Erstelle einen Circuit
Du benötigst mindestens einen Circuit als Eingabe für das Sampler-Primitive.
import numpy as np
from qiskit.circuit.library import efficient_su2
circuit = efficient_su2(127, entanglement="linear")
circuit.measure_all()
# The circuit is parametrized, so we will define the parameter values for execution
param_values = np.random.rand(circuit.num_parameters)
Verwende den Transpiler, um einen ISA-Circuit zu erhalten.
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
print(f">>> Circuit ops (ISA): {isa_circuit.count_ops()}")
>>> Circuit ops (ISA): OrderedDict([('sx', 3089), ('rz', 3036), ('cz', 1092), ('measure', 127), ('barrier', 1)])
3. Initialisiere den Qiskit Runtime Sampler
Wenn du den Sampler initialisierst, verwende den Parameter mode, um den Modus anzugeben, in dem er ausgeführt werden soll. Mögliche Werte sind batch, session oder backend-Objekte für Batch-, Session- und Job-Ausführungsmodus. Weitere Informationen findest du unter Introduction to Qiskit Runtime execution modes. Beachte, dass Open Plan-Benutzer keine Session-Jobs übermitteln können.
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(mode=backend)
4. Rufe den Sampler auf und erhalte Ergebnisse
Rufe als Nächstes die Methode run() auf, um die Ausgabe zu generieren. Der Circuit und optionale Parameterwertesätze werden als Primitive Unified Bloc (PUB)-Tupel eingegeben.
job = sampler.run([(isa_circuit, param_values)])
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
>>> Job ID: d5k96rsjt3vs73ds5tig
>>> Job Status: QUEUED
result = job.result()
# Get results for the first (and only) PUB
pub_result = result[0]
print(
f"First ten results for the 'meas' output register: {pub_result.data.meas.get_bitstrings()[:10]}"
)
First ten results for the 'meas' output register: ['0101001101010000011001110001011000010010001100001000100110011111011110000010110001101000110011101010000100011011000110101111000', '0100111000000100110001100100000101111000111001101000110111101110110010010100001101001111001010011101010000010011000110000010001', '0101111101111111010011010101000000110100000010000010011101100011100011001100000100100001000101000000100001010101010011001101100', '1100110101111111001110010000010100101010101010001000001100100110011111010000000010001000110111010000010101100000100000110111001', '0010000001111001111010100100010111101000101000100000101100001000011100000100011010110110100011100110001001110110111101010011000', '0101110000001000100100010010100100111000010100000000010010000000010110010010000110000001110110010100000111001110100100111101100', '0100011111101001000111110011011101101101110101110001010111011101111110011101001000000001110000011110000101010000001010000100000', '0001010101011000110100000100111111100001011000111110000011000111001101010000010001001100000110000000100000110101010010101110010', '0100011010001110011110000110100101100100101001001111010100100101010100010000000010100000101010110010000000001000010101011111110', '0000011000000111000001000101111111110110101100110000001100010010011101011100001010000100011010001010001101000000000000010001001']
Erste Schritte mit Backend-Primitives
Im Gegensatz zu anbieterspezifischen Primitives sind Backend-Primitives generische Implementierungen, die mit einem beliebigen backend-Objekt verwendet werden können, solange es die Backend-Schnittstelle implementiert.
- Das Sampler-Primitive kann mit jedem Anbieter durch Verwendung von
qiskit.primitives.BackendSamplerV2ausgeführt werden. - Das Estimator-Primitive kann mit jedem Anbieter durch Verwendung von
qiskit.primitives.BackendEstimatorV2ausgeführt werden.
Einige Anbieter implementieren Primitives nativ. Einzelheiten findest du auf der Qiskit Ecosystem-Seite.
Beispiel: BackendEstimator
from qiskit.primitives import BackendEstimatorV2
from <some_qiskit_provider> import QiskitProvider
provider = QiskitProvider()
backend = provider.get_backend('backend_name')
estimator = BackendEstimatorV2(backend)
Beispiel: BackendSampler
from qiskit.primitives import BackendSamplerV2
from <some_qiskit_provider> import QiskitProvider
provider = QiskitProvider()
backend = provider.get_backend('backend_name')
sampler = BackendSamplerV2(backend)
Gemeinsamkeiten und Unterschiede zwischen Backend- und Runtime-Primitives
-
Die Eingaben und Ausgaben von
qiskit.primitives.BackendSamplerV2undqiskit.primitives.BackendEstimatorV2folgen dem gleichen PUB-Format wie die Primitives in Qiskit Runtime. Einzelheiten findest du unter Primitive inputs and outputs. Es kann jedoch Unterschiede in den Feldern der zurückgegebenen Metadaten geben. -
Die Klasse
qiskit.primitives.BackendEstimatorV2bietet standardmäßig keine Mess- oder Gate-Fehlerminderungs-Implementierungen, da Backend-Primitives für die lokale Ausführung auf dem Computer des Benutzers konzipiert sind. -
Die Klasse
qiskit.primitives.BackendSamplerV2erfordert ein Backend, das die Optionmemoryunterstützt. -
Die Backend-Primitive-Schnittstellen stellen benutzerdefinierte
SamplerV2- undEstimatorV2-Optionsbereit, die sich von den Runtime-Implementierungen unterscheiden.
Nächste Schritte
- Erfahre, wie du lokal testen kannst, bevor du auf Quantencomputern ausführst.
- Sieh dir detaillierte Primitives-Beispiele an.
- Übe mit Primitives, indem du die Lektion Cost function lesson in IBM Quantum Learning durcharbeitest.
- Erfahre, wie du lokal im Abschnitt Transpile transpilierst.
- Probiere den Leitfaden Compare transpiler settings aus.
- Erfahre, wie du die Primitive-Optionen verwendest.
- Sieh dir die API für Sampler- und Estimator-Optionen an.
- Lies Migrate to V2 primitives.