Stima lato client
qiskit_ibm_runtime.executor_estimator
Panoramica
qiskit_ibm_runtime.executor_estimator.Estimator è un'implementazione dell'interfaccia EstimatorV2 Qiskit basata sulla primitiva Executor . Stima i valori attesi delle osservabili quantistiche eseguendo circuiti ISA su un backend IBM Quantum.
La differenza fondamentale tra la vecchia implementazione lato server e Estimator questa nuova implementazione è che tutte le operazioni di pre-elaborazione e post-elaborazione vengono eseguite sul computer client. Ciò comprende la preparazione del circuito (twirling, gate folding, disaccoppiamento dinamico e iniezione di rumore), nonché la post-elaborazione dei risultati (ridimensionamento TREX, estrapolazione ZNE e ponderazione con quasi-probabilità PEC). L'esecuzione di questi passaggi in locale garantisce un feedback più rapido durante il debug e un maggiore controllo da parte dell'utente.
Quando un utente invia un lavoro tramite run(), l'elaborazione sottostante consiste in:
- Forzare i blocchi unificati primitivi (PUB), risolvere le impostazioni predefinite relative al livello di resilienza e determinare il numero di colpi.
- Conversione dei PUB in un
QuantumProgram, applicando trasformazioni circuitali (twirling, gate folding, DD, iniezione di rumore) in base alle opzioni specificate. - Chiamata
Executorper inviare il programma quantistico al backend. - Al termine del lavoro, si procederà a stimare i valori attesi dai dati di misurazione grezzi e, se necessario, ad applicare una post-elaborazione volta a ridurre gli errori.
In caso di carichi di lavoro di grandi dimensioni o complessi, le fasi di pre-elaborazione e post-elaborazione lato client possono richiedere un elevato impiego di risorse e causare un ritardo nell'invio del lavoro. Imposta il logger qiskit_ibm_runtime su INFO per monitorare l'elaborazione lato client:
import logging
logger = logging.getLogger("qiskit_ibm_runtime")
logger.setLevel(logging.INFO)Utilizzo di base
Esempio 1 — Minimo (senza mitigazione degli errori)
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 valueEsempio 2 — Livello di resilienza 2 (riduzione degli errori di misurazione + ZNE con gate-folding)
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 levelEsempio 3 — PEC (richiede l'apprendimento esplicito del rumore)
A differenza dell'implementazione tradizionale lato server, questa implementazione lato client richiede Estimator un apprendimento esplicito del rumore per i metodi di mitigazione degli errori che necessitano di un modello di rumore (PEC e PEA).
Utilizza find_unique_layers() per estrarre i livelli di gate univoci dai tuoi PUB, invia i livelli a NoiseLearnerV3 per apprendere il loro rumore in un processo separato, quindi assegna le mappe di rumore apprese a 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)Input
Ogni chiamata a run() accetta un elenco di PUB. Ogni file “ PUB ” ha il seguente formato:
(<single circuit>, <one or more observables>, <optional parameter values>, <optional precision>)Per ulteriori informazioni sugli input e gli output di Estimator, consultare la sezione “Input e output di Estimator”.
Gli elementi provenienti dagli osservabili e i valori dei parametri vengono combinati seguendo le regole di broadcasting dell' NumPy, come descritto nella sezione “Input e output primitivi ”.
Opzioni
Quando si crea un'istanza di Estimator, è possibile passare delle opzioni utilizzando o EstimatorOptions un dizionario. Le opzioni di uso comune, come resilience_level, si trovano al primo livello. Altre opzioni sono raggruppate in categorie, come ad esempio execution. Specificare le opzioni in questo formato: options.<category>.<option> = <value>. Ad esempio: options.dynamical_decoupling.enable = True.
Per una panoramica sulla definizione delle opzioni primitive, consultare la sezione " Introduzione alle opzioni". Per ulteriori informazioni sulle opzioni di Estimator, consultare le sezioni " Specificare le opzioni di Estimator" e " Configurare la gestione del rumore con Estimator".
Output
run() restituisce un RuntimeJobV2. La chiamata restituisce job.result() un di PrimitiveResult oggetti EstimatorPubResult — uno per ogni PUB in ingresso:
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 metadataIl contenuto di dipende pub_result.data dalla tecnica di mitigazione specificata.
Nessuna misura di mitigazione / solo misure di mitigazione (livelli di resilienza 0 e 1)
Tutti i campi seguenti hanno la forma pub_shape, ovvero broadcast(param_shape, obs_shape).
data.evs— Valori attesi.data.stds— Deviazioni standard. Indica la dispersione tra le randomizzazioni del twirling quando questa funzione è abilitata; è pari a quandoensemble_standard_erroril twirling è disabilitato.data.ensemble_standard_error— Errore standard nell’ipotesi di rumore di scatto distribuito in modo indipendente e identico (senza contributo di deriva).
Quando è attiva la funzione di correzione delle misurazioni (TREX), i valori evs vengono corretti per tenere conto degli errori di lettura tramite un circuito di calibrazione che viene azionato automaticamente insieme ai circuiti principali.
Pec
Il PEC produce gli stessi tre campi dello scenario senza misure di mitigazione: evs, stds, e ensemble_standard_error. Il fattore di quasi-probabilità gamma viene applicato internamente durante la post-elaborazione e non compare come campo di output separato.
I valori stds sono normalizzati in base al fattore gamma, pertanto risultano in genere più elevati rispetto al caso senza mitigazione a parità di numero di scatti. Questo è il costo fondamentale del PEC: le stime non distorte comportano una maggiore varianza proporzionale al sovraccarico di campionamento (gamma^2).
ZNE (ripiegabile) e PEA
In tal caso resilience.zne_mitigation=True, lo stimatore esegue il circuito a diversi livelli di amplificazione del rumore e adatta una curva per estrapolare il valore a rumore zero. Il risultato contiene sia la stima estrapolata che i dati grezzi per ciascun livello di rumore.
data.evs— Valori attesi estrapolati a rumore zero (migliore adattamento eterogeneo — l’estrapolatore viene scelto termine per termine per le grandezze osservabili a più termini). Forma:pub_shape.data.stds— Deviazioni standard dei valori estrapolati. Ha la stessa forma dievs. Derivato dallo spread relativo alle randomizzazioni da twirling quando la funzione twirling è attiva.data.evs_noise_factors— Valori attesi grezzi (non estrapolati) per ciascun livello di amplificazione del rumore. Forma:(*pub_shape, num_noise_factors).data.stds_noise_factors— Deviazioni standard per ciascun fattore di rumore. Ha la stessa forma dievs_noise_factors. Indica la dispersione rispetto alle randomizzazioni con twirling quando il twirling è attivo; è pari a quandoensemble_stds_noise_factorsil twirling è disattivato.data.ensemble_stds_noise_factors— Errori standard dell’insieme per ciascun fattore di rumore, nell’ipotesi di rumore di shot distribuito in modo indipendente e identico. Forma:(*pub_shape, num_noise_factors).data.evs_extrapolated— Valori attesi ottenuti da ciascun estrapolatore richiesto, calcolati in ogni punto diresilience.zne.extrapolated_noise_factors. Si tratta di adattamenti omogenei forzati — lo stesso estrapolatore viene applicato a tutti i termini di un osservabile a più termini — un adattamento per ogni estrapolatore. Forma:(*pub_shape, num_extrapolators, num_eval_points).data.stds_extrapolated— Deviazioni standard corrispondenti aevs_extrapolated. Stessa forma.
Per le grandezze osservabili a più termini (ad esempio, {"XX": 0.5, "XY": 0.5}), e evs si stds ricorre a un adattamento eterogeneo: l’estrapolatore che meglio si adatta viene selezionato in modo indipendente per ciascun termine di Pauli. evs_extrapolated e stds_extrapolated utilizzare un adattamento omogeneo per ciascun estrapolatore, il che risulta utile per confrontare i modelli. Se la tua analisi richiede l'applicazione coerente di un unico estrapolatore, suddividi l'osservabile a più termini in osservabili a termine singolo, in modo che ciascun termine venga adattato separatamente.
I risultati di ZNE possono essere visualizzati con e draw_zne_evs() draw_zne_extrapolators() (richiede plotly).
Metadati relativi al livello di mansione
result.metadata è un che contiene dict :
"options"— la versione definitivaEstimatorOptions, come un dizionario. Le sotto-opzioni di resilienza inattive vengono eliminate (ad esempio, ilznesottodizionario viene omesso quandozne_mitigation=False), e il modello di rumore (se fornito) viene rimosso."target_precision"— la precisione ricavata dai PUB e dall’argomentoprecisiondirun(), oppureNonese nessuno dei due è specificato. In tal caso, il conteggio dei fotogrammi proviene dadefault_shots, ricorrendo in alternativa adefault_precision."shots"— il numero totale di colpi utilizzati per l'esecuzione."executor"— i metadati del risultato dell'Executor sottostante.
Guida alla migrazione
Questa implementazione di Estimator lato client costituisce in gran parte un sostituto diretto di quella precedente. Segui i passaggi elencati di seguito per effettuare la migrazione alla nuova implementazione, tenendo presenti queste modifiche comportamentali:
- La pre-elaborazione e la post-elaborazione avvengono sul lato client. Nell'Estimator precedente, tutte le trasformazioni dei circuiti (twirling, gate folding e iniezione di rumore), così come la post-elaborazione dei risultati (estrapolazione ZNE, riscalatura TREX e ponderazione PEC), vengono eseguite sul lato server. In questa implementazione lato client, questi passaggi vengono eseguiti interamente sul computer client.
- L'apprendimento del rumore è una fase a sé stante. Nell'Estimator tradizionale, l'apprendimento del rumore per PEC e PEA è integrato nel processo stesso dell'Estimator e gestito implicitamente sul lato server. In questa nuova implementazione, l'apprendimento del rumore è un flusso di lavoro separato che deve essere eseguito in modo esplicito.
- I processi di Executor sono stati inviati. L'Estimator lato client utilizza Executor per inviare i lavori, rendendoli così lavori Executor anziché lavori Estimator. Gli attributi del processo, come e
primitive_idinputs, restituiscono informazioni relative al processo Executor.
Passaggio 1 — Aggiornare le importazioni.
Prima:
from qiskit_ibm_runtime import Estimator
from qiskit_ibm_runtime.options import EstimatorOptionsDopo:
from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime.options_models import EstimatorOptionsFase 2 — Eseguire esplicitamente l'apprendimento del rumore (se si utilizza PEC o PEA).
Se il tuo codice utilizza PEC (pec_mitigation=True) o ZNE con PEA (zne.amplifier="pea"), devi eseguire esplicitamente l'apprendimento del rumore utilizzando NoiseLearnerV3.
Prima:
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)Dopo:
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)Fase 3 — Suddividere un lavoro in più lavori (se i PUB utilizzano valori di precisione diversi).
Le precisioni miste non sono più supportate: un lavoro non può più contenere PUB che richiedono valori di precisione diversi e, se IBMInputValueError ciò dovesse verificarsi, viene run() generato un errore. Raggruppa i PUB in base alla precisione e invia un lavoro per ogni gruppo, utilizzando un Batch in modo che i gruppi continuino a essere eseguiti insieme.
Prima:
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)Dopo:
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]Classi
Rubrica 1 | Rubrica 2 |
|---|---|
Estimator | Primitiva di calcolo lato client per IBM Quantum Compute (precedentemente Qiskit Runtime ). |
EstimatorV2 | alias di Estimator |