Entradas y salidas del estimador
El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos. Recomendamos utilizar estas versiones o posteriores.
qiskit[all]~=2.5.0 qiskit-ibm-runtime~=0.47.0
Esta página ofrece una descripción general de las entradas y salidas de la primitiva « Qiskit Runtime Estimator», que ejecuta cargas de trabajo en recursos de computación de IBM Quantum®. Estimator te permite definir de forma eficiente cargas de trabajo vectorizadas mediante una estructura de datos denominada « PUB » (). Se utilizan como entradas para el run() método de la primitiva Estimator, que ejecuta la carga de trabajo definida como un trabajo. A continuación, una vez finalizado el trabajo, los resultados se devuelven en un formato que depende tanto de los PUB utilizados como de las opciones de ejecución especificadas en la primitiva.
Entradas
Cada archivo « PUB » tiene este formato:
(<single circuit>, <one or more observables>, <optional one or more parameter values>, <optional precision>),
El parámetro opcional parameter values puede ser una lista o un único parámetro. 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 el tema «Entradas y salidas primitivas», y se devuelve una estimación del valor esperado para cada elemento de la forma difundida.
Si la entrada contiene medidas, estas se ignoran.
En el caso de la primitiva «Estimator», un « PUB » puede contener como máximo cuatro valores:
- Un único elemento
QuantumCircuit, que puede contener uno o másParameterobjetos - Una lista de uno o varios observables, que especifican los valores esperados que se van a estimar, organizados en una matriz (por ejemplo, un único observable representado como una matriz de dimensión 0, una lista de observables como una matriz de dimensión 1, y así sucesivamente). Los datos pueden estar en cualquiera de los siguientes
ObservablesArrayLikeformatos:PauliSparsePauliOp,PauliList,, ostr.Variables de desplazamiento- Con este método se agrupan los observables de desplazamiento que se encuentran en el mismo « PUB ».
- Las variables observables de desplazamiento en diferentes PUB, aunque compartan el mismo circuito, no se estiman utilizando la misma medición. Cada PUB representa una base de medición diferente y, por lo tanto, se requieren mediciones independientes para cada PUB.
- Para garantizar que las variables observables relacionadas con los desplazamientos se calculen utilizando la misma medida, agrúpalas en el mismo « PUB ».
- Un conjunto de valores de parámetros con los que se va a vincular el circuito. Esto se puede especificar como un único objeto similar a una matriz, en el que el último índice corresponde a los
Parameterobjetos del circuito, o bien se puede omitir (o, lo que es lo mismo, establecerse enNone) si el circuito no tieneParameterobjetos. - (Opcional) Una precisión objetivo para los valores esperados que se van a estimar
El siguiente código muestra un conjunto de entradas vectorizadas para la Estimator primitiva y las ejecuta en un backend de IBM® como un único RuntimeJobV2 objeto.
from qiskit.circuit import (
Parameter,
QuantumCircuit,
)
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime import (
QiskitRuntimeService,
EstimatorV2 as Estimator,
)
import numpy as np
# Instantiate runtime service and get
# the least busy backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# Define a circuit with two parameters.
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.ry(Parameter("a"), 0)
circuit.rz(Parameter("b"), 0)
circuit.cx(0, 1)
circuit.h(0)
# Transpile the circuit
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
transpiled_circuit = pm.run(circuit)
layout = transpiled_circuit.layout
# Now define a sweep over parameter values, the last axis of dimension 2 is
# for the two parameters "a" and "b"
params = np.vstack(
[
np.linspace(-np.pi, np.pi, 100),
np.linspace(-4 * np.pi, 4 * np.pi, 100),
]
).T
# Define three observables. The inner length-1 lists cause this array of
# observables to have shape (3, 1), rather than shape (3,) if they were
# omitted.
observables = [
[SparsePauliOp(["XX", "IY"], [0.5, 0.5])],
[SparsePauliOp("XX")],
[SparsePauliOp("IY")],
]
# Apply the same layout as the transpiled circuit.
observables = [
[observable.apply_layout(layout) for observable in observable_set]
for observable_set in observables
]
# Estimate the expectation value for all 300 combinations of observables
# and parameter values, where the pub result will have shape (3, 100).
#
# This shape is due to our array of parameter bindings having shape
# (100, 2), combined with our array of observables having shape (3, 1).
estimator_pub = (transpiled_circuit, observables, params)
# Instantiate the new Estimator object, then run the transpiled circuit
# using the set of parameters and observables.
estimator = Estimator(mode=backend)
job = estimator.run([estimator_pub])
result = job.result()Resultados
Una vez que se envían uno o varios PUB a una QPU para su ejecución y un trabajo se completa con éxito, los datos se devuelven como un objeto PrimitiveResult contenedor al que se accede llamando al RuntimeJobV2.result() método.
El objeto PrimitiveResult contiene una lista iterable de PubResult objetos que recogen los resultados de la ejecución de cada PUB.
Cada elemento de esta lista se corresponde con cada PUB enviado al método de la run() primitiva (por ejemplo, un trabajo enviado con 20 PUBs devolverá un PrimitiveResult objeto que contiene una lista de 20 PubResult objetos, uno correspondiente a cada PUB ).
Cada primitiva PubResult del estimador contiene, como mínimo, una matriz de valores esperados (PubResult.data.evs) y las desviaciones estándar asociadas (ya sea PubResult.data.stds o, PubResult.data.ensemble_standard_error dependiendo del resilience_level utilizado), pero puede contener más datos en función de las opciones de mitigación de errores que se hayan especificado.
Cada PubResult objeto posee un atributo data y un metadata atributo.
- El
dataatributo es un campo personalizadoDataBinque contiene los valores de medición reales, las desviaciones estándar, etc. - El
DataBinpresenta diversos atributos en función de la forma o estructura del objeto « PUB » asociado, así como de las opciones de mitigación de errores especificadas por la primitiva utilizada para enviar el trabajo (por ejemplo, ZNE o PEC ). - El
metadataatributo contiene información sobre el tiempo de ejecución y las opciones de mitigación de errores utilizadas (como se explica más adelante en la sección «Metadatos del resultado» de esta página).
A continuación se ofrece un esquema visual de la estructura PrimitiveResult de datos de la salida del Estimador:
└── PrimitiveResult
├── PubResult[0]
│ ├── metadata
│ └── data ## In the form of a DataBin object
│ ├── evs
│ │ └── List of estimated expectation values in the shape
| | specified by the first pub
│ └── stds
│ └── List of calculated standard deviations in the
| same shape as above
├── PubResult[1]
| ├── metadata
| └── data ## In the form of a DataBin object
| ├── evs
| │ └── List of estimated expectation values in the shape
| | specified by the second pub
| └── stds
| └── List of calculated standard deviations in the
| same shape as above
├── ...
├── ...
└── ...
En pocas palabras, una tarea devuelve un PrimitiveResult objeto y contiene una lista de uno o más PubResult objetos. A continuación, estos PubResult objetos almacenan los datos de medición de cada « PUB » que se haya enviado al trabajo.
El siguiente fragmento de código describe el formato PrimitiveResult (y los elementos asociados PubResult) del trabajo creado anteriormente.
print(
f"The result of the submitted job had {len(result)} "
f"PUBs and has a value:\n {result}\n"
)
print(
"The associated PubResult of this job has the following data bins:\n "
"{result[0].data}\n"
)
print(f"And this DataBin has attributes: {result[0].data.keys()}")
print(
"Recall that this shape is due to our array of parameter binding sets"
"having shape (100, 2), where 2 is the number of parameters in the "
"circuit, combined with our array of observables having shape (3, 1). \n"
)
with np.printoptions(threshold=200):
print(
"The expectation values measured from this PUB are: \n"
"{result[0].data.evs}\n"
)Output:
The result of the submitted job had 1 PUBs and has a value:
PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(3, 100), dtype=float64>), stds=np.ndarray(<shape=(3, 100), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(3, 100), dtype=float64>), shape=(3, 100)), 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})
The associated PubResult of this job has the following data bins:
{result[0].data}
And this DataBin has attributes: dict_keys(['evs', 'stds', 'ensemble_standard_error'])
Recall that this shape is due to our array of parameter binding setshaving shape (100, 2), where 2 is the number of parameters in the circuit, combined with our array of observables having shape (3, 1).
The expectation values measured from this PUB are:
{result[0].data.evs}
Cómo calcula el error la primitiva Estimator
Además de la estimación de la media de las variables observables pasadas en los PUB de entrada (el evs campo de la DataBin), el estimador también intenta proporcionar una estimación del error asociado a esos valores esperados. Todas las consultas de Estimator rellenarán el stds campo con una cantidad equivalente al error estándar de la media para cada valor esperado, pero algunas opciones de mitigación de errores proporcionan información adicional, como ensemble_standard_error.
Consideremos una única variable observable . En ausencia de ZNE, podemos considerar que cada iteración de la ejecución del estimador proporciona una estimación puntual del valor esperado . Si las estimaciones puntuales forman un vector Os, entonces el valor devuelto en ensemble_standard_error es equivalente a lo siguiente (donde es la desviación estándar de la estimación del valor esperado y es el número de iteraciones):
que considera todos los planos como parte de un único conjunto. Si has solicitado el giro de puertas (twirling.enable_gates = True), puedes clasificar las estimaciones puntuales de en conjuntos que compartan un giro común. Denominemos a estos conjuntos de estimaciones O_twirls, y hay num_randomizations (número de giros) de ellos. Entonces stds es el error estándar de la media de O_twirls, tal y como se indica en
donde es la desviación estándar de O_twirls y es el número de giros. Cuando no se activa el efecto giratorio, stds y ensemble_standard_error son iguales.
Si se activa ZNE, los parámetros stds descritos anteriormente se convierten en coeficientes de un modelo de regresión no lineal para un modelo de extrapolación. Lo que finalmente se devuelve en este stds caso es la incertidumbre del modelo de ajuste evaluada con un factor de ruido igual a cero. Cuando el ajuste es deficiente o existe una gran incertidumbre en el ajuste, el valor obtenido stds puede llegar a ser muy elevado. Cuando se activa ZNE, pub_result.data.evs_noise_factors y también pub_result.data.stds_noise_factors se rellenan, de modo que puedas realizar tu propia extrapolación.
Metadatos del resultado
Además de los resultados de la ejecución, tanto el objeto PrimitiveResult como PubResult el contienen un atributo de metadatos sobre el trabajo que se envió. Los metadatos que contienen información sobre todos los PUB enviados (como las distintas opciones de tiempo de ejecución disponibles) se encuentran en el PrimitiveResult.metatada, mientras que los metadatos específicos de cada PUB se encuentran en PubResult.metadata.
En el campo de metadatos, las implementaciones de primitivas pueden devolver cualquier información sobre la ejecución que les resulte relevante, y no hay pares clave-valor garantizados por la primitiva base. Por lo tanto, los metadatos devueltos pueden variar según la implementación de la primitiva.
# Print out the results metadata
print("The metadata of the PrimitiveResult is:")
for key, val in result.metadata.items():
print(f"'{key}' : {val},")
print("\nThe metadata of the PubResult result is:")
for key, val in result[0].metadata.items():
print(f"'{key}' : {val},")Output:
The metadata of the PrimitiveResult is:
'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,
The metadata of the PubResult result is:
'shots' : 4096,
'target_precision' : 0.015625,
'circuit_metadata' : {},
'resilience' : {},
'num_randomizations' : 32,