Skip to main content
IBM Quantum Platform

Estimador del lado del cliente

qiskit_ibm_runtime.executor_estimator


Visión general

qiskit_ibm_runtime.executor_estimator.Estimator es una implementación de la interfaz EstimatorV2 de Qiskit basada en la primitiva Executor . Calcula los valores esperados de las observables cuánticas mediante la ejecución de circuitos ISA en un backend de IBM Quantum.

La diferencia fundamental entre la implementación anterior del lado del servidor y Estimator esta nueva implementación es que todo el procesamiento previo y posterior se lleva a cabo en el equipo del cliente. Esto incluye la preparación del circuito (twirling, plegado de compuertas, desacoplamiento dinámico e inyección de ruido), así como el posprocesamiento de los resultados (reescalado TREX, extrapolación ZNE y ponderación cuasi-probabilística PEC). La ejecución de estos pasos de forma local permite obtener una respuesta más rápida durante la depuración y ofrece un mayor control al usuario.

Cuando un usuario envía un trabajo a través de run(), el procesamiento subyacente consiste en:

  1. Forzar los bloques unificados primitivos (PUB), resolver los valores predeterminados del nivel de resiliencia y determinar el número de disparos.
  2. Convertir los archivos PUB en un QuantumProgram, aplicando transformaciones de circuitos (twirling, gate folding, DD, inyección de ruido) según las opciones especificadas.
  3. Llamada Executor para enviar el programa cuántico al backend.
  4. Una vez finalizado el trabajo, se calcularán los valores esperados a partir de los datos de medición sin procesar y se aplicará un posprocesamiento para mitigar los errores, según sea necesario.
Nota

En el caso de cargas de trabajo grandes o complejas, los pasos de preprocesamiento y posprocesamiento del lado del cliente pueden consumir muchos recursos y provocar un retraso antes de que se envíe el trabajo. Configura el registrador qiskit_ibm_runtime INFO para supervisar el procesamiento del lado del cliente:

import logging
logger = logging.getLogger("qiskit_ibm_runtime")
logger.setLevel(logging.INFO)

Utilización básica

Ejemplo 1 — Mínimo (sin mitigación de errores)

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 value

Ejemplo 2 — Nivel de resiliencia 2 (mitigación de errores de medición + ZNE con pliegue en puerta)

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 level

Ejemplo 3 — PEC (requiere un aprendizaje explícito del ruido)

A diferencia de la implementación tradicional del lado del servidor, esta del lado del cliente Estimator requiere un aprendizaje explícito del ruido para los métodos de mitigación de errores que necesitan un modelo de ruido (PEC y PEA).

Utiliza find_unique_layers() para extraer las capas de puerta únicas de tus PUB, pasa las capas a NoiseLearnerV3 para aprender su ruido en un trabajo independiente y, a continuación, asigna los mapas de ruido aprendidos 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)

Entradas

Cada llamada a run() toma como argumento una lista de PUB. Cada archivo « PUB » tiene este formato:

(<single circuit>, <one or more observables>, <optional parameter values>, <optional precision>)

Consulta «Entradas y salidas del estimador» para obtener más información sobre las entradas y salidas del estimador.

Los elementos de los observables y los valores de los parámetros se combinan siguiendo las reglas de difusión de « NumPy », tal y como se describe en «Entradas y salidas primitivas ».


Opciones

Al crear una instancia de Estimator, puedes pasar opciones utilizando o EstimatorOptions un diccionario. Las opciones más habituales, como resilience_level, se encuentran en el primer nivel. Las demás opciones se agrupan en categorías, como, por ejemplo, execution. Especifica las opciones con este formato: options.<category>.<option> = <value>. Por ejemplo: options.dynamical_decoupling.enable = True.

Consulta la sección «Introducción a las opciones» para obtener una visión general sobre cómo especificar opciones primitivas. Consulta «Especificar opciones de Estimator» y «Configurar la gestión del ruido con Estimator» para obtener más información sobre las opciones de Estimator.


Resultados

run() devuelve un RuntimeJobV2. La llamada devuelve job.result() un conjunto de PrimitiveResult objetos EstimatorPubResult —uno por cada PUB de entrada—:

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 metadata

El contenido de depende pub_result.data de la técnica de mitigación especificada.

Sin medidas de mitigación / únicamente medidas de mitigación (niveles de resiliencia 0 y 1)

Todos los campos siguientes tienen la forma pub_shape, que es broadcast(param_shape, obs_shape).

  • data.evs — Valores esperados.
  • data.stds — Desviaciones estándar. Refleja la dispersión entre las aleatorizaciones de «twirling» cuando esta función está activada; es igual a cuando ensemble_standard_error está desactivada.
  • data.ensemble_standard_error — Error estándar bajo el supuesto de que el ruido de disparo sigue una distribución independiente e idéntica (sin contribución por deriva).

Cuando la función de corrección de mediciones (TREX) está activa, los valores evs se corrigen para compensar los errores de lectura mediante un circuito de calibración que funciona automáticamente junto con los circuitos principales.

Pec

PEC genera los mismos tres campos que el caso sin medidas de mitigación: evs, stds, y ensemble_standard_error. El factor de cuasiprobabilidad gamma se aplica internamente durante el posprocesamiento y no aparece como un campo de salida independiente.

Los valores stds se ajustan mediante el factor gamma, por lo que suelen ser mayores que en el caso sin medidas de mitigación para el mismo número de disparos. Este es el coste fundamental del PEC: las estimaciones no sesgadas conllevan una mayor varianza proporcional a la sobrecarga de muestreo (gamma^2).

ZNE (plegable por la parte superior) y PEA

Cuando resilience.zne_mitigation=True, el estimador hace funcionar el circuito a distintos niveles de amplificación del ruido y ajusta una curva para extrapolar hasta el ruido cero. El resultado incluye tanto la estimación extrapolada como los datos brutos para cada nivel de ruido.

  • data.evs — Valores esperados extrapolados sin ruido (mejor ajuste heterogéneo: el extrapolador se elige término por término para observables de varios términos). Forma: pub_shape.
  • data.stds — Desviaciones estándar de los valores extrapolados. Tiene la misma forma que evs. Se deriva de la dispersión observada en las aleatorizaciones con «twirling» cuando esta función está activada.
  • data.evs_noise_factors — Valores esperados brutos (sin extrapolar) en cada nivel de amplificación del ruido. Forma: (*pub_shape, num_noise_factors).
  • data.stds_noise_factors — Desviaciones estándar para cada factor de ruido. Tiene la misma forma que evs_noise_factors. Refleja la dispersión en las aleatorizaciones de «twirling» cuando esta función está activada; es igual a cuando ensemble_stds_noise_factors está desactivada.
  • data.ensemble_stds_noise_factors — Errores estándar del conjunto para cada factor de ruido, bajo el supuesto de que el ruido de disparo sigue una distribución independiente e idéntica. Forma: (*pub_shape, num_noise_factors).
  • data.evs_extrapolated — Valores esperados de cada extrapolador solicitado, evaluados en cada punto de resilience.zne.extrapolated_noise_factors. Se trata de ajustes homogéneos forzados —se aplica el mismo extrapolador a todos los términos de una observable de varios términos—: un ajuste por cada extrapolador. Forma: (*pub_shape, num_extrapolators, num_eval_points).
  • data.stds_extrapolated — Desviaciones estándar correspondientes a evs_extrapolated. La misma forma.
Nota

Para observables con varios términos (por ejemplo, {"XX": 0.5, "XY": 0.5}), evs y stds utilizan un ajuste heterogéneo: el extrapolador que mejor se ajusta se selecciona de forma independiente para cada término de Pauli. evs_extrapolated y stds_extrapolated utilizar un ajuste homogéneo por extrapolador, lo cual resulta útil para comparar modelos. Si tu análisis requiere aplicar un único extrapolador de forma coherente, divide la variable observable de varios términos en variables observables de un solo término, de modo que cada término se ajuste por separado.

Los resultados de ZNE se pueden visualizar con y draw_zne_evs() draw_zne_extrapolators() (requiere plotly).

Metadatos a nivel de trabajo

result.metadata es un que contiene dict :

  • "options" — la versión definitiva EstimatorOptions, a modo de diccionario. Se eliminan las subopciones de resiliencia inactivas (por ejemplo, se omite el subdiccionario zne cuando zne_mitigation=False) y se elimina el modelo de ruido (si se ha proporcionado).
  • "target_precision" — la precisión determinada a partir de los PUB y el precision argumento de run(), o None si no se ha especificado ninguno de los dos. En ese caso, el recuento de disparos procede de default_shots, y se recurre a default_precision.
  • "shots" — el número total de disparos utilizados para la ejecución.
  • "executor" — los metadatos del resultado del Executor subyacente.

Guía de migración

Esta implementación del Estimator del lado del cliente es, en gran medida, un sustituto directo de la anterior. Sigue los pasos que se indican a continuación para migrar a la nueva implementación, teniendo en cuenta estos cambios de comportamiento:

  • El preprocesamiento y el posprocesamiento se realizan en el lado del cliente. En el Estimador heredado, todas las transformaciones de circuitos (giro, plegado de compuertas e inyección de ruido), así como el posprocesamiento de los resultados (extrapolación ZNE, reescalado TREX y ponderación PEC), se realizan en el servidor. En esta implementación del lado del cliente, estos pasos se ejecutan íntegramente en el equipo del cliente.
  • El aprendizaje del ruido es un paso independiente. En el Estimador tradicional, el aprendizaje del ruido para PEC y PEA está integrado en la propia tarea del Estimador y se gestiona de forma implícita en el lado del servidor. En esta nueva implementación, el aprendizaje del ruido es un flujo de trabajo independiente que debe llevarse a cabo de forma explícita.
  • Se han enviado los trabajos del ejecutor. El Estimator del lado del cliente utiliza Executor para enviar trabajos, por lo que estos se convierten en trabajos de Executor en lugar de trabajos de Estimator. Los atributos del trabajo, como y primitive_id inputs, devuelven información sobre el trabajo del ejecutor.

Paso 1 — Actualiza las importaciones.

Antes:

from qiskit_ibm_runtime import Estimator
from qiskit_ibm_runtime.options import EstimatorOptions

Después:

from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime.options_models import EstimatorOptions

Paso 2 — Realizar el aprendizaje del ruido de forma explícita (si se utiliza PEC o PEA).

Si tu código utiliza PEC (pec_mitigation=True) o ZNE con PEA (zne.amplifier="pea"), debes llevar a cabo el aprendizaje de ruido de forma explícita utilizando NoiseLearnerV3.

Antes:

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)

Después:

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)

Paso 3 — Dividir un trabajo en varios (si los PUB utilizan valores de precisión diferentes).

Ya no se admiten precisiones mixtas: un trabajo ya no puede contener PUB que soliciten valores de precisión diferentes, y, si IBMInputValueError lo hace, se produce run() un error. Agrupa los PUB por precisión y envía un trabajo por grupo, utilizando un Batch para que los grupos se ejecuten al mismo tiempo.

Antes:

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)

Después:

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]

Clases

Columna « 1 »
Columna « 2 »
EstimatorPrimitiva «Estimator» del lado del cliente para IBM Quantum Compute (anteriormente Qiskit Runtime ).
EstimatorV2alias de Estimator
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.