Estimador con la API REST
Versiones del paquete
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.3.0
Los pasos de este tema describen cómo ejecutar y configurar cargas de trabajo mediante la API REST, y muestran cómo invocarlas en cualquier programa que elijas.
Esta documentación utiliza el módulo requests Python para mostrar el funcionamiento de la API REST. No obstante, este flujo de trabajo se puede ejecutar utilizando cualquier lenguaje o marco de trabajo que permita trabajar con API REST. Consulta la documentación de referencia de la API para obtener más detalles.
1. Inicializar la cuenta
Dado que Estimator es un servicio gestionado, primero debes configurar tu cuenta. A continuación, puedes seleccionar el dispositivo que quieras utilizar para calcular el valor esperado.
En este tema encontrarás información sobre cómo iniciar sesión en tu cuenta, ver los backends disponibles e invalidar tokens.
2. Crear un circuito QASM
Necesitas al menos un circuito como entrada para la primitiva Estimator.
Defina un circuito cuántico QASM. Por ejemplo:
qasm_string='''
OPENQASM 3;
include "stdgates.inc";
qreg q[2];
creg c[2];
x q[0];
cx q[0], q[1];
c[0] = measure q[0];
c[1] = measure q[1];
'''Los siguientes fragmentos de código dan por hecho que se qasm_string ha compilado en una nueva cadena resulting_qasm.
3. Ejecuta el circuito cuántico utilizando la API « V2 » de Estimator
Los siguientes trabajos utilizan las primitivas IBM Quantum y V2. Tanto SamplerV2 como EstimatorV2 toman como entrada uno o más bloques primitivos unificados (PUB). Cada « PUB » es una tupla que contiene un circuito y los datos transmitidos a dicho circuito, que pueden ser varios observables y parámetros. Cada PUB devuelve un resultado.
import requests
url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"
headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each.
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
}}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")4. Comprueba el estado del trabajo y obtén los resultados
A continuación, pasa el job_id a la API:
response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')Resultado
>>> Job ID: 58223448-5100-4dec-a47a-942fb30edcad
>>> Job Status: JobStatus.RUNNINGVer resultados de empleo:
response_result= requests.get(url+'/'+job_id+'/results', headers=headers)
res_dict=response_result.json()
estimator_result=res_dict['results']
print(estimator_result)Resultado
[{'data': {'evs': 0.7428980350102542, 'stds': 0.029884014518789213, 'ensemble_standard_error': 0.03261147170624149}, 'metadata': {'shots': 10016, 'target_precision': 0.01, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}}]5. Trabajar con opciones
Las técnicas de mitigación de errores permiten a los usuarios mitigar los errores de los circuitos mediante la modelización del ruido del dispositivo en el momento de la ejecución. Esto suele traducirse en una sobrecarga de preprocesamiento cuántico relacionada con el entrenamiento del modelo, y en una sobrecarga de posprocesamiento clásico para mitigar los errores en los resultados brutos mediante el uso del modelo generado.
Las técnicas de mitigación de errores integradas en las primitivas son opciones avanzadas de resiliencia. Para especificar estas opciones, utiliza la resilience_level opción al enviar tu trabajo.
Los siguientes ejemplos muestran las opciones predeterminadas para el desacoplamiento dinámico, el twirling y TREX + ZNE. Encontrarás más opciones y detalles adicionales en el tema «Técnicas de mitigación y supresión de errores ».
TREX + ZNE
import requests
url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "BACKEND_NAME"
headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"options": {
"resilience": {
"measure_mitigation": True,
"zne_mitigation": True,
"zne": {
"extrapolator":["exponential", "linear"],
"noise_factors":[1, 3, 5],
},
},
},
}
}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")Desacoplamiento dinámico
import requests
url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "BACKEND_NAME"
headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"options": {
"dynamical_decoupling": {
"enable": True,
"sequence_type": 'XpXm',
"extra_slack_distribution": 'middle',
"scheduling_method": 'alap',
},
},
}
}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")Girando
import requests
url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "BACKEND_NAME"
headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"options": {
"twirling": {
"enable_gates": True,
"enable_measure": True,
"num_randomizations": "auto",
"shots_per_randomization": "auto",
"strategy": "active-accum",
},
},
}
}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")Circuitos parametrizados
1. Inicializar la cuenta
Primero tienes que activar tu cuenta. A continuación, puedes seleccionar el dispositivo en el que deseas realizar los cálculos.
En este tema encontrarás información sobre cómo iniciar sesión en tu cuenta, ver los backends disponibles e invalidar tokens.
2. Definir los parámetros
import requests
import qiskit_ibm_runtime
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.qasm3 import dumps
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit import transpile
service = QiskitRuntimeService(channel='ibm_quantum')
backend = service.backend("<SPECIFY BACKEND>")
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
theta = Parameter('theta')
phi = Parameter('phi')
parameter_values = {'theta': 1.57, 'phi': 3.14} # In case we want to pass a dictionary3. Crear un circuito cuántico y añadir puertas parametrizadas
qc = QuantumCircuit(2)
# Add parameterized gates
qc.rx(theta, 0)
qc.ry(phi, 1)
qc.cx(0, 1)
qc.measure_all()
# Draw the original circuit
qc.draw('mpl')
# Get an ISA circuit
isa_circuit = pm.run(qc)4. Generar código QASM 3
qasm_str = dumps(isa_circuit)
print("Generated QASM 3 code:")
print(qasm_str)5. Ejecuta el circuito cuántico mediante la API de Estimator V2
import requests
url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"
headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"params": {
# Choose one option: direct parameter transfer or through a dictionary
#"pubs": [[qasm_str,[1,2],500]], # primitive unified blocs (PUBs) containing one circuit each.
"pubs": [[qasm_str,parameter_values,500]], # primitive unified blocs (PUBs) containing one circuit each.
}}
response = requests.post(url, headers=headers, json=job_input)
if response.status_code == 200:
job_id = response.json().get('id')
print(f"Job created: {response.text}")
else:
print(f"Error: {response.status_code}")print(response.text)6. Comprueba el estado del trabajo y obtén los resultados
A continuación, pasa el job_id a la API:
response_status_singlejob = requests.get(f"{url}/{job_id}", headers=headers)
response_status_singlejob.json().get('state')Resultado
{'status': 'Completed'}Ver resultados de empleo:
response_result = requests.get(f"{url}/{job_id}/results", headers=headers)
res_dict=response_result.json()
# Get results for the first PUB
counts=res_dict['results'][0]['data']['c']['samples']
print(counts[:20])Resultado
['0x1', '0x2', '0x1', '0x2', '0x1', '0x2', '0x0', '0x2', '0x1', '0x1', '0x2', '0x2', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1']Próximos pasos
- Hay varias formas de ejecutar cargas de trabajo, según tus necesidades: modo de trabajo, modo de sesión y modo por lotes. Descubre cómo trabajar con el modo de sesión y el modo por lotes en el apartado sobre modos de ejecución. Ten en cuenta que los usuarios de Open Plan no pueden enviar trabajos de sesión.
- Descubre cómo configurar tu cuenta mediante la API REST.
- Practica con primitivas siguiendo la lección sobre la función «Cost» en IBM Quantum® Learning.
- Descubre cómo realizar la transpilación de forma local en la sección «Transpilación ».