Estimador com a API REST
Versões do pacote
O código desta página foi desenvolvido com base nos seguintes requisitos. Recomendamos usar essas versões ou versões mais recentes.
qiskit[all]~=2.3.0
As etapas descritas neste tópico explicam como executar e configurar cargas de trabalho usando a API REST e mostram como invocá-las em qualquer programa de sua escolha.
Esta documentação utiliza o módulo requestsPython para demonstrar a API REST Qiskit Runtime. No entanto, esse fluxo de trabalho pode ser executado usando qualquer linguagem ou estrutura que ofereça suporte ao trabalho com APIs REST. Consulte a documentação de referência da API para obter mais detalhes.
1. Inicializar a conta
Como o Estimador d Qiskit Runtime s é um serviço gerenciado, você precisa primeiro configurar sua conta. Você pode então selecionar o dispositivo que deseja usar para calcular o valor esperado.
Veja neste tópico como inicializar sua conta, visualizar os back-ends disponíveis e invalidar tokens.
2. Criar um circuito QASM
É necessário pelo menos um circuito como entrada para a primitiva Estimador.
Defina um circuito quântico QASM. Por exemplo:
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];
'''Os trechos de código a seguir pressupõem que o qasm_string tenha sido compilado em uma nova string resulting_qasm.
3. Execute o circuito quântico usando a API do Estimador V2
Os trabalhos a seguir utilizam as primitivas Qiskit Runtime V2. Tanto quanto SamplerV2 EstimatorV2 recebem um ou mais blocos primitivos unificados (PUBs) como entrada. Cada PUB é uma tupla que contém um circuito e os dados transmitidos para esse circuito, que podem ser vários observáveis e parâmetros. Cada chamada de PUB retorna um 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. Verificar o status do trabalho e obter os resultados
Em seguida, passe o job_id para a API:
response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')Saída
>>> Job ID: 58223448-5100-4dec-a47a-942fb30edcad
>>> Job Status: JobStatus.RUNNINGVeja os resultados da busca:
response_result= requests.get(url+'/'+job_id+'/results', headers=headers)
res_dict=response_result.json()
estimator_result=res_dict['results']
print(estimator_result)Saída
[{'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. Trabalhar com opções de tempo de execução
As técnicas de mitigação de erros permitem que os usuários minimizem os erros de circuito por meio da modelagem do ruído do dispositivo no momento da execução. Isso geralmente resulta em uma sobrecarga de pré-processamento quântico relacionada ao treinamento do modelo e em uma sobrecarga de pós-processamento clássico para mitigar erros nos resultados brutos por meio do uso do modelo gerado.
As técnicas de mitigação de erros integradas às primitivas são opções avançadas de resiliência. Para definir essas opções, use a resilience_level opção ao enviar seu trabalho.
Os exemplos a seguir demonstram as opções padrão para desacoplamento dinâmico, twirling e TREX + ZNE. Encontre mais opções e detalhes no tópico “Técnicas de mitigação e supressão de erros”.
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}")Desacoplamento 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 a conta
Como o Qiskit Runtime é um serviço gerenciado, você precisa primeiro configurar sua conta. Você pode então selecionar o dispositivo no qual deseja realizar seus cálculos.
Veja neste tópico como inicializar sua conta, visualizar os back-ends disponíveis e invalidar tokens.
2. Definir 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. Crie um circuito quântico e adicione portas 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. Gerar código QASM 3
qasm_str = dumps(isa_circuit)
print("Generated QASM 3 code:")
print(qasm_str)5. Execute o circuito quântico usando a API do 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. Verificar o status do trabalho e obter os resultados
Em seguida, passe o job_id para a API:
response_status_singlejob = requests.get(f"{url}/{job_id}", headers=headers)
response_status_singlejob.json().get('state')Saída
{'status': 'Completed'}Veja os resultados da busca:
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])Saída
['0x1', '0x2', '0x1', '0x2', '0x1', '0x2', '0x0', '0x2', '0x1', '0x1', '0x2', '0x2', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1']Próximas etapas
- Existem várias maneiras de executar cargas de trabalho, dependendo das suas necessidades: modo de tarefa, modo de sessão e modo em lote. Saiba como trabalhar com o modo de sessão e o modo em lote no tópico sobre modos de execução. Observe que os usuários do Open Plan não podem enviar tarefas de sessão.
- Saiba como configurar sua conta usando a API REST.
- Pratique com primitivas seguindo a lição sobre a função
Costem IBM Quantum® Learning. - Saiba como fazer a transpilagem localmente na seção Transpilagem.