Clientseitiger Schätzer
qiskit_ibm_runtime.executor_estimator
Übersicht
qiskit_ibm_runtime.executor_estimator.Estimator ist eine Implementierung der Qiskit-Schnittstelle EstimatorV2 , die auf der Primitive Executor aufbaut. Es schätzt Erwartungswerte von Quantenobservablen, indem es ISA-Schaltkreise auf einem Backend des „ IBM Quantum “ ausführt.
Der wesentliche Unterschied zwischen der bisherigen serverseitigen Implementierung und Estimator dieser neuen Implementierung besteht darin, dass die gesamte Vor- und Nachbearbeitung auf dem Client-Rechner erfolgt. Dazu gehören die Vorbereitung der Schaltkreise (Twirling, Gate-Folding, dynamische Entkopplung und Rauscheinjektion) sowie die Nachbearbeitung der Ergebnisse (TREX-Skalierung, ZNE-Extrapolation und PEC-Quasi-Wahrscheinlichkeitsgewichtung). Die lokale Ausführung dieser Schritte ermöglicht ein schnelleres Feedback bei der Fehlersuche und bietet dem Benutzer mehr Kontrolle.
Wenn ein Benutzer einen Auftrag über [...], übermittelt run(), umfasst die zugrunde liegende Verarbeitung Folgendes:
- Die „Primitive Unified Blocs“ (PUBs) zusammenführen, die Standardwerte für die Ausfallsicherheit festlegen und die Anzahl der Schüsse bestimmen.
- Umwandlung der PUBs in ein
QuantumProgram, wobei Schaltungstransformationen (Twirling, Gate-Folding, DD, Rauscheinjektion) entsprechend den festgelegten Optionen angewendet werden. - Aufruf,
Executorum das Quantenprogramm an das Backend zu übermitteln. - Nach Abschluss des Auftrags werden aus den Rohmessdaten Erwartungswerte geschätzt und bei Bedarf eine Nachbearbeitung zur Fehlerminderung durchgeführt.
Bei umfangreichen oder komplexen Arbeitslasten können die clientseitigen Vor- und Nachbearbeitungsschritte ressourcenintensiv sein und zu einer Verzögerung führen, bevor der Auftrag übermittelt wird. Stellen Sie den Logger qiskit_ibm_runtime auf ein, INFO um die clientseitige Verarbeitung zu überwachen:
import logging
logger = logging.getLogger("qiskit_ibm_runtime")
logger.setLevel(logging.INFO)Grundlegende Verwendung
Beispiel 1 – Minimal (keine Fehlerbehebung)
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime.executor_estimator import Estimator
# Select a backend.
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
observable = SparsePauliOp("ZZ")
# Transform the circuit and observable into ISA format.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)
isa_obs = observable.apply_layout(isa_qc.layout)
estimator = Estimator(mode=backend)
estimator.options.resilience_level = 0
job = estimator.run([(isa_qc, isa_obs)])
result = job.result()
print(result[0].data.evs) # expectation valueBeispiel 2 – Resilienzstufe 2 (Minderung von Messfehlern + Gate-Folding-ZNE)
estimator = Estimator(mode=backend)
estimator.options.resilience_level = 2 # TREX + ZNE (gate folding)
job = estimator.run([(isa_qc, isa_obs)])
result = job.result()
print(result[0].data.evs) # zero-noise extrapolated expectation value
print(result[0].data.evs_noise_factors) # raw values at each noise amplification levelBeispiel 3 – PEC (erfordert explizites Rauschlernen)
Im Gegensatz zur bisherigen serverseitigen Implementierung erfordert Estimator diese clientseitige Variante ein explizites Rauschlernen für die Fehlerminderungsmethoden, die ein Rauschmodell benötigen (PEC und PEA).
Verwenden Sie, um find_unique_layers() die eindeutigen Gate-Schichten aus Ihren PUBs zu extrahieren, übergeben Sie die Schichten an, NoiseLearnerV3 um deren Rauschen in einem separaten Job zu ermitteln, und weisen Sie anschließend die ermittelten Rauschkarten zu layer_noise_model.
from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3
pubs = [(isa_qc, isa_obs)]
estimator = Estimator(mode=backend)
estimator.options.resilience.pec_mitigation = True
# Step 1. Extract the unique boxed gate layers from your PUBs.
layers = estimator.find_unique_layers(pubs)
# Step 2. Learn the noise model for those layers.
nl_result = NoiseLearnerV3(mode=backend).run(layers).result()
# Step 3. Convert the NoiseLearnerV3 result to Pauli-Lindblad maps and pass them
# to the Estimator. The maps follow the same order as the input layers, so they can
# be zipped positionally.
pauli_lindblad_maps = nl_result.to_pauli_lindblad_maps()
estimator.options.resilience.layer_noise_model = zip(layers, pauli_lindblad_maps)
job = estimator.run(pubs)
result = job.result()
print(result[0].data.evs)Eingaben
Jeder Aufruf von run() erfordert eine Liste von PUBs. Jede „ PUB “-Datei hat folgendes Format:
(<single circuit>, <one or more observables>, <optional parameter values>, <optional precision>)Weitere Informationen zu den Ein- und Ausgängen des Schätzers finden Sie unter „Ein- und Ausgänge des Schätzers“.
Elemente aus Observables und Parameterwerten werden gemäß den in „Primitive Ein- und Ausgänge“ beschriebenen „ NumPy “-Broadcasting-Regeln kombiniert.
Optionen
Beim Instanziieren Estimatorvon können Sie Optionen mithilfe von oder EstimatorOptions einem Wörterbuch übergeben. Häufig verwendete Optionen, wie beispielsweise resilience_level, befinden sich auf der ersten Ebene. Weitere Optionen sind in Kategorien zusammengefasst, wie zum Beispiel execution. Geben Sie die Optionen in diesem Format an: options.<category>.<option> = <value>. Zum Beispiel: options.dynamical_decoupling.enable = True.
Einen Überblick über die Angabe von Basisoptionen finden Sie unter „Einführung in Optionen “. Weitere Informationen zu den Optionen des Estimators finden Sie unter „Estimator-Optionen festlegen“ und „Rauschmanagement mit dem Estimator konfigurieren “.
Ausgaben
run() gibt ein RuntimeJobV2. zurück. Der Aufruf gibt job.result() eine Reihe von PrimitiveResult Objekten EstimatorPubResult zurück – eines pro Eingabe- PUB :
result = job.result()
pub_result = result[0] # EstimatorPubResult for the first PUB
pub_result.data # DataBin holding numerical arrays
pub_result.metadata # dictionary with per-PUB metadata
result.metadata # dictionary with job-level metadataDer Inhalt von pub_result.data hängt von der angegebenen Schutzmaßnahme ab.
Keine Maßnahmen / ausschließlich Messmaßnahmen (Resilienzstufen 0 und 1)
Alle folgenden Felder haben die Form pub_shape, die gleich ist broadcast(param_shape, obs_shape).
data.evs— Erwartungswerte.data.stds— Standardabweichungen. Gibt die Streuung über die Twirling-Zufallsgenerierungen wieder, wenn Twirling aktiviert ist; entspricht,ensemble_standard_errorwenn Twirling deaktiviert ist.data.ensemble_standard_error— Standardfehler unter der Annahme eines unabhängig und identisch verteilten Schussrauschens (ohne Driftbeitrag).
Wenn die Messwertkorrektur (TREX) aktiv ist, werden die Werte evs mithilfe einer Kalibrierschaltung, die automatisch parallel zu den Hauptschaltungen betrieben wird, um Ablesefehler korrigiert.
PEC
PEC erzeugt dieselben drei Felder wie das Szenario ohne Minderungsmaßnahmen: evs, stds, und ensemble_standard_error. Der Gamma-Quasi-Wahrscheinlichkeitsfaktor wird intern während der Nachbearbeitung angewendet und erscheint nicht als separates Ausgabefeld.
Die Werte stds werden mit dem Gamma-Faktor skaliert, sodass sie bei gleicher Schusszahl in der Regel größer sind als im Fall ohne Minderung. Dies ist der grundlegende Nachteil von PEC: Unverzerrte Schätzungen gehen mit einer erhöhten Varianz einher, die proportional zum Stichprobenaufwand ist (gamma^2).
ZNE (Gate-Folding) und PEA
In resilience.zne_mitigation=Truediesem Fall lässt der Schätzer die Schaltung bei verschiedenen Rauschverstärkungsstufen durchlaufen und passt eine Kurve an, um auf ein Rauschen von Null zu extrapolieren. Das Ergebnis enthält sowohl die extrapolierte Schätzung als auch die Rohdaten für jedes Rauschpegel.
data.evs— Rauschfreie extrapolierte Erwartungswerte (beste heterogene Anpassung – bei mehrgliedrigen Observablen wird der Extrapolator für jeden Glied einzeln gewählt). Form:pub_shape.data.stds— Standardabweichungen der extrapolierten Werte. Gleiche Form wieevs. Abgeleitet aus der Streuung bei „Twirling“-Zufallsgenerierung, wenn „Twirling“ aktiviert ist.data.evs_noise_factors— Rohwerte (nicht extrapolierte Erwartungswerte) bei jedem Rauschverstärkungsgrad. Form:(*pub_shape, num_noise_factors).data.stds_noise_factors— Standardabweichungen bei jedem Rauschfaktor. Gleiche Form wieevs_noise_factors. Gibt die Streuung bei aktivierter Twirling-Funktion an; entsprichtensemble_stds_noise_factorsbei deaktivierter Twirling-Funktion.data.ensemble_stds_noise_factors— Standardfehler des Ensembles bei jedem Rauschfaktor unter der Annahme, dass das Schussrauschen unabhängig und identisch verteilt ist. Form:(*pub_shape, num_noise_factors).data.evs_extrapolated— Erwartungswerte der einzelnen angeforderten Extrapolatoren, berechnet an jedem Punkt inresilience.zne.extrapolated_noise_factors. Es handelt sich hierbei um erzwungene homogene Anpassungen – auf alle Terme einer mehrtermigen Observablen wird derselbe Extrapolator angewendet –, d. h. eine Anpassung pro Extrapolator. Form:(*pub_shape, num_extrapolators, num_eval_points).data.stds_extrapolated— Standardabweichungen, die … entsprechenevs_extrapolated. Gleiche Form.
Bei Observablen mit mehreren Termen (zum Beispiel {"XX": 0.5, "XY": 0.5}) stds verwenden evs und eine heterogene Anpassung: Der am besten passende Extrapolator wird für jeden Pauli-Term unabhängig ausgewählt. evs_extrapolated und stds_extrapolated verwenden Sie eine homogene Anpassung pro Extrapolator, was für den Vergleich von Modellen nützlich ist. Wenn für Ihre Analyse ein einziger Extrapolator konsistent angewendet werden muss, teilen Sie die aus mehreren Termen bestehende Observable in einzelne Observables auf, sodass jeder Term für sich allein angepasst wird.
ZNE-Ergebnisse können mit und draw_zne_evs() visualisiert werden ( draw_zne_extrapolators() erfordert plotly).
Metadaten auf Jobebene
result.metadata ist ein, das Folgendes enthält dict :
"options"— die endgültige FassungEstimatorOptions, als Wörterbuch. Inaktive Unteroptionen für die Resilienz werden entfernt (beispielsweise wird das Unterwörterbuchzneweggelassen, wennzne_mitigation=False), und das Rauschmodell (sofern vorhanden) wird entfernt."target_precision"— die aus den PUBs ermittelte Genauigkeit und dasprecisionArgument vonrun(), oder,Nonefalls keines von beiden angegeben ist. In diesem Fall stammt die Schussanzahl ausdefault_shots, wobei auf zurückgegriffen wirddefault_precision."shots"— die Gesamtzahl der für die Ausführung verwendeten Schüsse."executor"— die Metadaten des zugrunde liegenden Executor-Ergebnisses.
Migrationshandbuch
Diese clientseitige Implementierung des Estimators ist im Wesentlichen ein direkter Ersatz für die bisherige Version. Befolgen Sie die unten aufgeführten Schritte, um auf die neue Implementierung umzustellen, und beachten Sie dabei die folgenden Verhaltensänderungen:
- Die Vor- und Nachbearbeitung erfolgt auf der Client-Seite. Im bisherigen Estimator werden alle Schaltungstransformationen (Twirling, Gate-Folding und Rauscheinjektion) sowie die Nachbearbeitung der Ergebnisse (ZNE-Extrapolation, TREX-Skalierung und PEC-Gewichtung) serverseitig durchgeführt. Bei dieser clientseitigen Implementierung werden diese Schritte vollständig auf dem Client-Rechner ausgeführt.
- Das Lernen von Rauschen ist ein separater Schritt. Im bisherigen Estimator ist das Rauschlernen für PEC und PEA in den Estimator-Job selbst integriert und wird serverseitig implizit abgewickelt. In dieser neuen Implementierung ist das Rauschlernen ein separater Arbeitsablauf, der explizit durchgeführt werden muss.
- Executor-Jobs werden übermittelt. Der clientseitige Estimator nutzt den Executor zum Einreichen von Aufträgen, wodurch diese zu Executor-Aufträgen und nicht zu Estimator-Aufträgen werden. Job-Attribute wie und
primitive_idinputsliefern Informationen zum Executor-Job zurück.
Schritt 1 – Aktualisieren Sie die Importe.
Bisher:
from qiskit_ibm_runtime import Estimator
from qiskit_ibm_runtime.options import EstimatorOptionsNachher:
from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime.options_models import EstimatorOptionsSchritt 2 – Führen Sie das Rauschlernen explizit durch (falls PEC oder PEA verwendet wird).
Wenn Ihr Code PEC (pec_mitigation=True) oder ZNE mit PEA (zne.amplifier="pea") verwendet, müssen Sie das Rauschlernen explizit mithilfe von durchführen NoiseLearnerV3.
Bisher:
from qiskit_ibm_runtime import Estimator
pubs = [...] # Your PUBs
estimator = Estimator(mode=backend)
estimator.options.resilience.pec_mitigation = True # or zne_mitigation + pea amplifier
job = estimator.run(pubs)Nachher:
from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime import NoiseLearnerV3
pubs = [...] # Your PUBs
estimator = Estimator(mode=backend)
estimator.options.resilience.pec_mitigation = True # or zne_mitigation + pea amplifier
# Identify the unique layers to learn.
layers = estimator.find_unique_layers(pubs)
# Learn the noise model for those layers (runs as a separate job).
learner = NoiseLearnerV3(mode=backend)
learner_job = learner.run(layers)
learner_result = learner_job.result()
# Convert the result to Pauli-Lindblad noise maps.
pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()
# Assign the learned noise maps so PEA/PEC uses them.
# The result objects returned by NoiseLearnerV3 follow the same order as the input
# layers, so the positional zip can be used here.
estimator.options.resilience.layer_noise_model = zip(layers, pauli_lindblad_maps)
# Now execute the target PUBs.
job = estimator.run(pubs)Schritt 3 – Einen Auftrag in mehrere Aufträge aufteilen (falls die PUBs unterschiedliche Genauigkeitswerte verwenden).
Gemischte Genauigkeiten werden nicht mehr unterstützt: Ein Auftrag darf keine PUBs mehr enthalten, die unterschiedliche Genauigkeitswerte anfordern; IBMInputValueError andernfalls wird ein Fehler run() ausgelöst. Gruppieren Sie die PUBs nach Präzision und reichen Sie pro Gruppe einen Auftrag ein, wobei Sie ein verwenden, Batch damit die Gruppen weiterhin gemeinsam ausgeführt werden.
Bisher:
from qiskit_ibm_runtime import Estimator
# PUBs with different precision values.
pubs = [(isa_circuit, isa_obs, None, 0.1), (isa_circuit1, isa_obs1, None, 0.5)]
estimator = Estimator(mode=backend)
job = estimator.run(pubs)Nachher:
from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime import Batch
# Group the PUBs by precision, one group per job.
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
jobs = [
estimator.run([(isa_circuit, isa_obs)], precision=0.1),
estimator.run([(isa_circuit1, isa_obs1)], precision=0.5),
]
results = [job.result() for job in jobs]Klassen
Kolumne „ 1 “ | Kolumne „ 2 “ |
|---|---|
Estimator | Clientseitige „Estimator“-Primitive für „ IBM Quantum Compute “ (früher „ Qiskit Runtime “). |
EstimatorV2 | Alias von Estimator |