Calcular los valores esperados en un algoritmo¶
La primitiva Estimator se usa para diseñar un algoritmo que calcula los valores esperados.
Antecedentes¶
El rol de la primitiva Estimator
es doble: actúa como un punto de entrada a los dispositivos cuánticos o simuladores, reemplazando la interfaz Backend
(comúnmente conocida como backend.run()
). Además, es una abstracción algorítmica para los cálculos del valor esperado, por lo que no tienes que construir manualmente el circuito final de valor esperado. Esto da como resultado una reducción considerable de la complejidad del código y un diseño de algoritmo más compacto.
Nota
Modelo del backend.run(): En este modelo, accediste a backends reales y simuladores remotos utilizando el módulo qiskit-ibmq-provider
(ahora migrado a qiskit-ibm-provider
). Para ejecutar simulaciones locales, puedes importar un backend específico de qiskit-aer
. Todos ellos siguieron la interfaz backend.run()
.
Code example for
qiskit-ibmq-provider
&backend.run()
from qiskit import IBMQ # Select provider provider = IBMQ.get_provider(hub="ibm-q", group="open", project="main") # Get backend backend = provider.get_backend("ibmq_qasm_simulator") # cloud simulator # Run result = backend.run(expectation_circuits)Code example for
qiskit-aer
&backend.run()
from qiskit_aer import AerSimulator # former import: from qiskit import Aer # Get local simulator backend backend = AerSimulator() # Run result = backend.run(expectation_circuits)
Modelo de primitivas: Accede a backends reales y simuladores remotos a través de las primitivas de qiskit-ibm-runtime
(Sampler
y Estimator
). Para ejecutar simulaciones locales, puedes importar primitivas local específicas de qiskit_aer.primitives
y qiskit.primitives
. Todas siguen las interfaces BaseSampler
y BaseEstimator
, pero solo las primitivas Runtime ofrecen acceso al servicio Runtime, las sesiones y la mitigación de errores integrada.
Code example for Runtime Estimator
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator # Define service service = QiskitRuntimeService() # Get backend backend = service.backend("ibmq_qasm_simulator") # cloud simulator # Define Estimator estimator = Estimator(backend=backend) # Run Expectation value calculation result = estimator.run(circuits, observables).result()Code example for Aer Estimator
from qiskit_aer import Estimator # Get local simulator Estimator estimator = Estimator() # Run expectation value calculation result = estimator.run(circuits, observables).result()
Si tu código calculaba previamente los valores esperados usando backend.run()
, lo más probable es que hayas usado el módulo qiskit.opflow
para manejar operadores y funciones de estado. Para admitir este escenario, el siguiente ejemplo de migración muestra cómo reemplazar el flujo de trabajo (qiskit.opflow
y backend.run()
) con un flujo de trabajo basado en Estimator
.
Ejemplo de principio a fin¶
1. Definición del problema¶
Queremos calcular el valor esperado de un estado cuántico (circuito) con respecto a un determinado operador. En este ejemplo, estamos usando la molécula de H2 y un circuito arbitrario como estado cuántico:
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
# Step 1: Define operator
op = SparsePauliOp.from_list(
[
("II", -1.052373245772859),
("IZ", 0.39793742484318045),
("ZI", -0.39793742484318045),
("ZZ", -0.01128010425623538),
("XX", 0.18093119978423156),
]
)
# Step 2: Define quantum state
state = QuantumCircuit(2)
state.x(0)
state.x(1)
1.a. [Anterior] Convertir el problema a opflow
¶
qiskit.opflow
proporcionaba sus propias clases para representar tanto a los operadores como a los estados cuánticos, por lo que el problema definido anteriormente se encapsularía como:
from qiskit.opflow import CircuitStateFn, PauliSumOp
opflow_op = PauliSumOp(op)
opflow_state = CircuitStateFn(state)
Este paso ya no es necesario cuando se utilizan las primitivas.
Nota
Para obtener instrucciones sobre cómo migrar desde qiskit.opflow
, consulta la guía de migración de opflow.
2. Calcular los valores esperados en un dispositivo real o simulador en la nube¶
2.a. [Anterior] Usar opflow
y backend.run()
¶
El flujo de trabajo anterior requería muchos pasos para calcular un valor esperado:
Nota
Reemplaza ibmq_qasm_simulator
con el nombre de tu dispositivo para ver el flujo de trabajo completo para un dispositivo real.
from qiskit.opflow import StateFn, PauliExpectation, CircuitSampler
from qiskit import IBMQ
# Define the state to sample
measurable_expression = StateFn(opflow_op, is_measurement=True).compose(opflow_state)
# Convert to expectation value calculation object
expectation = PauliExpectation().convert(measurable_expression)
# Define provider and backend
provider = IBMQ.get_provider(hub="ibm-q", group="open", project="main")
backend = provider.get_backend("ibmq_qasm_simulator")
# Inject backend into circuit sampler
sampler = CircuitSampler(backend).convert(expectation)
# Evaluate
expectation_value = sampler.eval().real
>>> print("expectation: ", expectation_value)
expectation: -1.065734058826613
2.b. [Nuevo] Usar la primitiva Estimator
de Runtime¶
El Estimator
simplifica la sintaxis del lado del usuario, convirtiéndolo en una herramienta más conveniente para el diseño de algoritmos.
Nota
Reemplaza ibmq_qasm_simulator
con el nombre de tu dispositivo para ver el flujo de trabajo completo para un dispositivo real.
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator
service = QiskitRuntimeService(channel="ibm_quantum")
backend = service.backend("ibmq_qasm_simulator")
estimator = Estimator(backend=backend)
expectation_value = estimator.run(state, op).result().values
Ten en cuenta que el Estimator devuelve una lista de valores, ya que puede realizar evaluaciones por lotes.
>>> print("expectation: ", expectation_value)
expectation: [-1.06329149]
La primitiva Estimator
de Runtime ofrece una serie de características y opciones de ajuste que no tienen una alternativa en el modo anterior a ser migrada, pero pueden ayudar a mejorar tu rendimiento y resultados. Para obtener más información, consulta lo siguiente:
3. Otras alternativas de ejecución (no Runtime)¶
Esta sección describe cómo usar primitivas que no son de Runtime para probar un algoritmo usando simulación local. Supongamos que queremos resolver el problema definido anteriormente con una simulación de vector de estado local.
3.a. [Anterior] Usar el simulador Qiskit Aer¶
from qiskit.opflow import StateFn, PauliExpectation, CircuitSampler
from qiskit_aer import AerSimulator
# Define the state to sample
measurable_expression = StateFn(opflow_op, is_measurement=True).compose(opflow_state)
# Convert to expectation value calculation object
expectation = PauliExpectation().convert(measurable_expression)
# Define statevector simulator
simulator = AerSimulator(method="statevector", shots=100)
# Inject backend into circuit sampler
circuit_sampler = CircuitSampler(simulator).convert(expectation)
# Evaluate
expectation_value = circuit_sampler.eval().real
>>> print("expectation: ", expectation_value)
expectation: -1.0636533500290943
3.b. [Nuevo] Usar la primitiva Estimator
de referencia o el Estimator
de Aer¶
El Estimator
de referencia te permite realizar una simulación exacta o ruidosa basada en iteraciones de la clase Statevector
en el módulo qiskit.quantum_info
.
from qiskit.primitives import Estimator
estimator = Estimator()
expectation_value = estimator.run(state, op).result().values
# for shot-based simulation:
expectation_value = estimator.run(state, op, shots=100).result().values
>>> print("expectation: ", expectation_value)
expectation: [-1.03134297]
Todavía puedes acceder al Simulador Aer a través de su Estimator
dedicado. Esto puede ser útil para realizar simulaciones con modelos de ruido. En este ejemplo, el método de simulación se ha actualizado para que coincida con el resultado de 3.a.
from qiskit_aer.primitives import Estimator # import change!!!
estimator = Estimator(run_options= {"method": "statevector"})
expectation_value = estimator.run(state, op, shots=100).result().values
>>> print("expectation: ", expectation_value)
expectation: [-1.06365335]
Para obtener más información sobre el uso de las primitivas Aer, consulta el tutorial de VQE .
Para obtener más información sobre cómo ejecutar simulaciones ruidosas con las primitivas de Runtime, consulta este tema.