QESEM: Uma função Qiskit da Qedma
Consulte a referência da API
O código desta página foi desenvolvido com base nos seguintes requisitos. Recomendamos o uso dessas versões ou versões mais recentes.
qiskit[all]~=2.5.0 qiskit-ibm-runtime~=0.47.0
As funções do Qiskit são um recurso experimental disponível apenas para usuários dos planos IBM Quantum® Premium Plan, Flex Plan e On-Prem (via IBM Quantum Platform API). Eles estão no status de versão prévia e estão sujeitos a alterações.
Visão geral
Embora as unidades de processamento quântico tenham melhorado significativamente nos últimos anos, os erros causados por ruído e imperfeições no hardware existente continuam sendo um grande desafio para os desenvolvedores de algoritmos quânticos. À medida que o campo se aproxima de cálculos quânticos em escala utilitária que não podem ser verificados classicamente, soluções para cancelar ruídos com precisão garantida estão se tornando cada vez mais importantes. Para superar esse desafio, a Qedma desenvolveu o Quantum Error Mitigation (QESEM), perfeitamente integrado ao IBM Quantum Platform como uma função Qiskit.
Com o QESEM, os usuários podem executar seus circuitos quânticos em QPUs sujeitas a ruído para obter resultados altamente precisos e livres de erros, com sobrecargas de tempo de QPU altamente eficientes, próximas aos limites fundamentais. Para isso, o QESEM utiliza um conjunto de métodos proprietários desenvolvidos pela Qedma, destinados à caracterização e à redução de erros. As técnicas de redução de erros incluem otimização de portas, transpilagem sensível ao ruído, supressão de erros (ES) e mitigação imparcial de erros (EM). Com essa combinação de métodos baseados em caracterização, os usuários podem obter resultados confiáveis e sem erros para circuitos quânticos genéricos de grande volume, possibilitando aplicações que não poderiam ser realizadas de outra forma.
Para uma descrição completa dos componentes subjacentes, bem como uma demonstração em escala utilitária, consulte o artigo Mitigação de erros confiável e de alta precisão para circuitos quânticos em escala utilitária.
Descrição
Você pode usar a função QESEM da Qedma para estimar e executar facilmente seus circuitos com supressão e atenuação de erros, obtendo maiores volumes de circuitos e maior precisão. Para usar o QESEM, você fornece um circuito quântico, um conjunto de observáveis a serem medidos, uma precisão estatística alvo para cada observável e uma QPU escolhida. Antes de executar o circuito com a precisão desejada, você pode estimar o tempo de QPU necessário com base em um cálculo analítico que não requer a execução do circuito. Quando estiver satisfeito com a estimativa de tempo da QPU, você poderá executar o circuito com o QESEM.
Quando você executa um circuito, o QESEM executa um protocolo de caracterização de dispositivo adaptado ao seu circuito, produzindo um modelo de ruído confiável para os erros que ocorrem no circuito. Com base na caracterização, o QESEM primeiro implementa a transpilagem sensível ao ruído para mapear o circuito de entrada em um conjunto de qubits e portas físicos, o que minimiza o ruído que afeta o observável alvo. Isso inclui os portões disponíveis nativamente (CX/CZ em dispositivos IBM® ), bem como portões adicionais otimizados pela QESEM, formando o conjunto de portões estendido da QESEM. O QESEM então executa um conjunto de circuitos ES e EM baseados em caracterização na QPU e coleta os resultados das medições. Em seguida, eles são processados posteriormente de maneira clássica para fornecer um valor esperado imparcial e uma barra de erro para cada observável, correspondendo à precisão solicitada.
Foi demonstrado que o QESEM fornece resultados de alta precisão para uma variedade de aplicações quânticas e nos maiores volumes de circuitos que podem ser obtidos atualmente. O QESEM oferece os seguintes recursos voltados para o usuário, demonstrados na seção de benchmarks abaixo:
- Precisão garantida: o QESEM produz estimativas imparciais para valores esperados de observáveis. Seu método EM é equipado com garantias teóricas que, juntamente com a caracterização de ponta da Qedma, asseguram que a mitigação converge para a saída do circuito sem ruído até a precisão especificada pelo usuário. Em contraste com muitos métodos EM heurísticos que são propensos a erros sistemáticos ou vieses, a precisão garantida do QESEM é essencial para garantir resultados confiáveis em circuitos quânticos genéricos e observáveis.
- Escalabilidade para QPUs grandes: o tempo de QPU do QESEM depende dos volumes dos circuitos, mas é independente do número de qubits. A Qedma demonstrou o QESEM nos maiores dispositivos quânticos disponíveis atualmente, incluindo os dispositivos Eagle de 127 qubits e Heron de 133 qubits da IBM Quantum.
- Independente do aplicativo: O QESEM foi demonstrado em uma variedade de aplicações, incluindo simulação Hamiltoniana, VQE, QAOA e estimativa de amplitude. Os usuários podem inserir qualquer circuito quântico e observável a ser medido e obter resultados precisos e sem erros. As únicas limitações são ditadas pelas especificações de hardware e pelo tempo alocado da QPU, que determinam os volumes de circuito acessíveis e as precisões de saída. Por outro lado, muitas soluções de redução de erros são específicas do aplicativo ou envolvem heurísticas não controladas, o que as torna inaplicáveis a circuitos e aplicativos quânticos genéricos.
- Conjunto de portas estendido: o QESEM suporta portas de ângulo fracionário e fornece portas de ângulo fracionário otimizadas para Qedma ( ) nos dispositivos IBM Quantum Heron e Eagle. Este conjunto de portas estendido permite uma compilação mais eficiente e desbloqueia volumes de circuito maiores em até 2 vezes em comparação com a compilação CX/CZ padrão.
- Observáveis multibase: O QESEM é compatível com observáveis de entrada compostos por muitas cadeias de Pauli não comutáveis, como Hamiltonianos genéricos. A escolha das bases de medição e a otimização da alocação de recursos da QPU (disparos e circuitos) são então executadas automaticamente pelo QESEM para minimizar o tempo necessário da QPU para a precisão solicitada. Essa otimização, que leva em conta as fidelidades do hardware e as taxas de execução, permite que você execute circuitos mais profundos e obtenha maior precisão.
Referências
O QESEM foi testado em uma ampla variedade de casos de uso e aplicativos. Os exemplos a seguir podem ajudá-lo a avaliar os tipos de cargas de trabalho que podem ser executados com o QESEM.
Uma figura-chave de mérito para quantificar a dificuldade da mitigação de erros e da simulação clássica para um determinado circuito e observável é o volume ativo : o número de portas CNOT que afetam o observável no circuito. O volume ativo depende da profundidade e da largura do circuito, do peso do observável e da estrutura do circuito, que determina o cone de luz do observável. Para obter mais detalhes, consulte a palestra do 2024 IBM Quantum Summit. O QESEM oferece um valor particularmente grande no regime de alto volume, fornecendo resultados confiáveis para circuitos e observáveis genéricos.
Aplicativo | Número de qubits | Dispositivo | Descrição do circuito | Precisão | Tempo total | Uso de tempo de execução |
|---|---|---|---|---|---|---|
| Circuito VQE | 8 | Eagle ( r3 ) | 21 camadas totais, 9 bases de medição, 1D chain | 98% | 35 min | 14 min |
| Chutou Ising | 28 | Eagle ( r3 ) | 3 camadas exclusivas x 3 etapas, 2D topologia heavy-hex | 97% | 22 min | 4 minutos |
| Chutou Ising | 28 | Eagle ( r3 ) | 3 camadas exclusivas x 8 etapas, 2D topologia heavy-hex | 97% | 116 min | 23 min |
| Simulação de Hamiltoniano Trotterizado | 40 | Eagle ( r3 ) | 2 camadas únicas x 10 degraus de Trotter, 1D chain | 97% | 3 horas | 25 min |
| Simulação de Hamiltoniano Trotterizado | 119 | Eagle ( r3 ) | 3 camadas exclusivas x 9 etapas de Trotter, 2D topologia heavy-hex | 95% | 6.5 horas | 45 min |
| Chutou Ising | 136 | Garça ( r2 ) | 3 camadas exclusivas x 15 etapas, 2D topologia heavy-hex | em 90% | 52 min | 9 min. |
A precisão é medida aqui em relação ao valor ideal do observável: , em que ' ' é a precisão absoluta da atenuação (definida pela entrada do usuário), e é o observável no circuito sem ruído. o "uso do tempo de execução" mede o uso do parâmetro de comparação no modo de lote (soma do uso de trabalhos individuais), enquanto o "tempo total" mede o uso no modo de sessão (tempo de parede do experimento), que inclui tempos clássicos e de comunicação adicionais. O QESEM está disponível para execução em ambos os modos, para que os usuários possam fazer o melhor uso de seus recursos disponíveis.
Os circuitos Kicked Ising de 28 qubits simulam o Discrete Time Quasicrystal estudado por Shinjo et al arXiv 2403.16718 e Q2B24 Tokyo ) em três circuitos conectados de ibm_kawasaki. Os parâmetros do circuito adotados aqui são , com um estado inicial ferromagnético . O observável medido é o valor absoluto da magnetização . O experimento Kicked Ising em escala de utilidade foi executado nos 136 melhores qubits do ibm_fez; esse benchmark específico foi executado no ângulo de Clifford , no qual o volume ativo cresce lentamente com a profundidade do circuito, o que - juntamente com as altas fidelidades do dispositivo - permite alta precisão em um curto tempo de execução.
Os circuitos de simulação de hamiltoniano troterizado são para um modelo Ising de campo transversal em ângulos fracionários: e , respectivamente (consulte Q2B24 em Tóquio ). O circuito em escala de utilidade foi executado nos 119 melhores qubits de ibm_brisbane, enquanto o experimento de 40 qubits foi executado na melhor cadeia disponível. A precisão é relatada para a magnetização; resultados de alta precisão também foram obtidos para observáveis de maior peso.
O circuito VQE foi desenvolvido em conjunto com pesquisadores do Center for Quantum Technology and Applications do Deutsches Elektronen-Synchrotron (DESY). O observável alvo aqui era um Hamiltoniano que consistia em um grande número de cadeias de Pauli não comutáveis, enfatizando o desempenho otimizado do QESEM para observáveis de várias bases. A atenuação foi aplicada a um ansatz otimizado classicamente; embora esses resultados ainda não tenham sido publicados, resultados da mesma qualidade serão obtidos para diferentes circuitos com propriedades estruturais semelhantes.
Introdução
Autentique-se usando sua chave de API IBM Quantum Platform e selecione a função QESEM Qiskit da seguinte forma. (Este trecho pressupõe que você já tenha salvo sua conta no seu ambiente local.)
import qiskit
from qiskit_ibm_catalog import QiskitFunctionsCatalog
catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# verify that you have access to the function
catalog.list()# load the function
qesem_function = catalog.load("qedma/qesem")Exemplos
Exemplo de trabalho de estimativa de tempo
A tarefa de estimativa de tempo é útil para estimar o tempo de QPU necessário para um determinado pub e backend_name. backend_name também pode ser configurado para qualquer backend de simulador; por exemplo, fake_fez.
O QESEM utiliza um método EM quase-probabilístico, baseado em caracterização. Esse método apresenta uma sobrecarga de tempo da QPU que varia aproximadamente da seguinte forma:
Onde é o volume ativo do circuito, é a precisão alvo e é a infidelidade das portas nativas.
Observe que "estimate_time_only": "empirical" o programa utiliza alguns minutos de tempo de QPU para estimar o tempo necessário para a tarefa (se o backend for um dispositivo real; se for um simulador, não é utilizado tempo de QPU). Isso geralmente leva cerca de 5 minutos, mas não mais do que 10 minutos. Se a infidelidade mudar drasticamente entre a tarefa de estimativa empírica de tempo e a tarefa de mitigação, o tempo de QPU também mudará drasticamente.
Para começar, experimente este exemplo básico de estimativa do tempo de QPU necessário para executar o QESEM para um determinado pub:
backend_name = "fake_fez"
circ = qiskit.QuantumCircuit(5)
circ.cx(0, 1)
circ.cx(2, 3)
circ.cx(1, 2)
circ.cx(3, 4)
avg_magnetization = qiskit.quantum_info.SparsePauliOp.from_sparse_list(
[("Z", [q], 1 / 5) for q in range(5)], num_qubits=5
)
other_observable = qiskit.quantum_info.SparsePauliOp.from_sparse_list(
[("ZZ", [0, 1], 1.0), ("XZ", [1, 4], 0.5)], num_qubits=5
)
time_estimation_job = qesem_function.run(
pubs=[(circ, [avg_magnetization, other_observable])],
options={
"estimate_time_only": "empirical",
},
backend_name=backend_name, # example: "fake_fez", "ibm_fez"
)time_estimate_result = (
time_estimation_job.result()
) # a list of results per pub (circuit)O trecho de código a seguir descreve como recuperar diferentes métricas de execução da tarefa de estimativa de tempo (estimate_time_only que está definida):
pub_result = time_estimate_result[0]
print(
f"The estimated QPU time for mitigation for this PUB is: {pub_result.metadata['time_estimation_sec']}"
)
print(
f"The QPU time that this time estimation job took is (here it is 0 because we used fake_fez): {pub_result.metadata['total_qpu_time']}"
)
print(
f"Gates fidelity measured during the experiment: {pub_result.metadata['gate_fidelities']}"
)
print(f"Total shots: {pub_result.metadata['total_shots']}")
print(f"Resource usage breakdown: {pub_result.metadata['resource_usage']}")Output:
The estimated QPU time for mitigation for this PUB is: 300
The QPU time that this time estimation job took is (here it is 0 because we used fake_fez): 0
Gates fidelity measured during the experiment: {'CZ': 0.9951354916722668, 'ID1Q': 0.9991246627329172}
Total shots: 220000
Resource usage breakdown: {'RUNNING: MAPPING': {'CPU_TIME': 33.6066133165732, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU_TIME': 184.53575124032795, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: WAITING_FOR_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: EXECUTING_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}}
Quando a estimativa empírica de tempo está ativada, o QESEM executa um pequeno número de circuitos para fornecer uma estimativa mais precisa do tempo de execução na QPU. Os resultados da mitigação desses circuitos estão disponíveis no empirical_estimation_mitigation_results campo do trabalho.
Como esses resultados foram obtidos a partir de uma amostra limitada de circuitos, eles são significativamente menos precisos do que os resultados finais obtidos a partir do trabalho completo de mitigação do QESEM. No entanto, quando o circuito é pequeno ou a precisão alvo é baixa, a mitigação realizada durante a estimativa empírica do tempo pode ser suficiente para atingir a precisão desejada, e talvez não seja necessário realizar todo o processo de mitigação.
O empirical_estimation_mitigation_results campo é uma lista de PrimitiveResult objetos por parâmetro de entrada. Se o circuito não estiver parametrizado, a lista terá comprimento 1.
empirical_estimation_mitigation_results = time_estimate_result[0].metadata[
"empirical_estimation_mitigation_results"
][0] # a list per parameterprint("Partial results for the observables:")
print(
f" Mitigated expectation values: {empirical_estimation_mitigation_results.data.evs}"
)
print(
f" Mitigated error bars: {empirical_estimation_mitigation_results.data.stds}"
)
print(
f" Number of shots used for mitigation: {empirical_estimation_mitigation_results.metadata['mitigation_shots']}"
)
transpiled_circ = empirical_estimation_mitigation_results.metadata[
"transpiled_circ"
]
print(f" Qubit mapping: {transpiled_circ['qubit_maps']}")
print(
f" Number of measurement bases: {transpiled_circ['num_measurement_bases']}\n"
)
# results per obs
emp_obs_results = empirical_estimation_mitigation_results.metadata["results"][
0
]
# print(f"Results for each observable: {results}")
print("Results for each observable:")
for i, (obs_array, result_dict) in enumerate(emp_obs_results):
# obs_array, result_dict = results
print(f"Observable {i+1}: {obs_array}")
print(
f" QESEM mitigated value: {result_dict['qesem']['value']} \u00b1 {result_dict['qesem']['error_bar']}"
)Output:
Partial results for the observables:
Mitigated expectation values: [1.00347302 1.00693905]
Mitigated error bars: [0.00304061 0.00714276]
Number of shots used for mitigation: 180000
Qubit mapping: [[[0, 136], [1, 143], [2, 142], [3, 141], [4, 140]]]
Number of measurement bases: 2
Results for each observable:
Observable 1: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 1.003473015776871 ± 0.0030406128032204015
Observable 2: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 1.0069390542613554 ± 0.0071427606736885925
Exemplo de tarefa de mitigação no QESEM
O exemplo a seguir executa um trabalho do QESEM:
sample_job = qesem_function.run(
pubs=[(circ, [avg_magnetization, other_observable])],
backend_name=backend_name, # example: "ibm_fez"
# options = {
# "estimate_time_only": "empirical",
# "default_precision": 0.2, # Default precision is applied to all pubs that don't have a precision specified, see API reference for more details
# "max_execution_time": 3600, # You can specify a maximum QPU time in seconds, see API reference for more details
# "transpilation_level": "standard", # "minimal_with_layout_opt" for minimal transpilation, see API reference for more details
# "parallel_execution": True, # True for parallel execution, see API reference for more details
# },
)Para obter uma descrição detalhada de cada campo de entrada e opção, consulte a referência da API do QESEM.
Você pode usar as APIs conhecidas do Qiskit Serverless para verificar o status da carga de trabalho do Qiskit Function ou retornar resultados:
# Print the ID so you can use it later, if necessary
print(sample_job.job_id)
print(sample_job.status())
sample_result = sample_job.result()Output:
3ac6b2df-15b0-4dc0-8f48-cf14bd20a1c8
DONE
O trecho de código a seguir demonstra como recuperar os resultados da mitigação e as métricas de execução. Esses dados contêm informações essenciais que permitem uma compreensão mais profunda de como os diferentes parâmetros afetam a execução do QESEM. Isso também pode ser relevante ao redigir um artigo com base em sua pesquisa.
for pub_idx, pub_result in enumerate(
sample_result
): # each element in the list is a result for a different pub, here we sent only one pub
print(f"\nPUB {pub_idx}:")
print(
f" The QPU time that this job took is (here it is 0 because we used fake_fez): {pub_result.metadata['total_qpu_time']}"
)
print(
f" Gates fidelity measured during the experiment: {pub_result.metadata['gate_fidelities']}"
)
print(f" Total shots: {pub_result.metadata['total_shots']}")
print(
f" Number of shots used for mitigation: {pub_result.metadata['mitigation_shots']}"
)
print(
f" Resource usage breakdown: {pub_result.metadata['resource_usage']}"
)Output:
PUB 0:
The QPU time that this job took is (here it is 0 because we used fake_fez): 0.0
Gates fidelity measured during the experiment: {'CZ': 0.9953704216147041, 'ID1Q': 0.9991834123567518}
Total shots: 446000
Number of shots used for mitigation: 194000
Resource usage breakdown: {'RUNNING: MAPPING': {'CPU_TIME': 32.52745003718883, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU_TIME': 257.850521848537, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: WAITING_FOR_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: EXECUTING_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}}
metadata["results"]Nesse caso, os resultados são agrupados primeiro por instância do circuito e, em seguida, por observável.
print("Full QESEM mitigation results:")
for pub_idx, pub_result in enumerate(sample_result):
print(f"\nPUB {pub_idx}:")
print(f" Mitigated expectation values: {pub_result.data.evs}")
print(f" Mitigated error bars: {pub_result.data.stds}")
noisy_results = pub_result.metadata.get("noisy_results")
print(f" Unmitigated expectation values: {noisy_results.evs}")
print(f" Unmitigated error bars: {noisy_results.stds}")
print(" Transpiled circuits:")
for circ_idx, transpiled_circ in enumerate(
pub_result.metadata["transpiled_circs"]
):
print(f" Circuit {circ_idx}:")
# print(f" Circuit: \n {transpiled_circ['circuit']}") # not printing it because it's long but you can see the transpiled circuit itself
print(f" Qubit mapping: {transpiled_circ['qubit_maps']}")
print(
f" Measurement bases: {transpiled_circ['num_measurement_bases']}"
)
print(" Results for each observable:")
for circ_idx, circ_results in enumerate(pub_result.metadata["results"]):
print(f" Circuit {circ_idx}:")
for obs_idx, (obs_array, result_dict) in enumerate(circ_results):
print(f" Observable {obs_idx}: {obs_array}")
print(
f" QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}"
)
print(
f" Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}"
)Output:
Full QESEM mitigation results:
PUB 0:
Mitigated expectation values: [1.00648343 1.00636289]
Mitigated error bars: [0.00253812 0.00693586]
Unmitigated expectation values: [0.98031429 0.96357143]
Unmitigated error bars: [0.00124128 0.00578812]
Transpiled circuits:
Circuit 0:
Qubit mapping: [[[0, 140], [1, 141], [2, 142], [3, 143], [4, 136]]]
Measurement bases: 2
Results for each observable:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 1.0064834305181962 ± 0.002538119914534849
Unmitigated value: 0.9803142857142859 ± 0.0012412835813609938
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 1.0063628870614818 ± 0.006935859820870656
Unmitigated value: 0.9635714285714285 ± 0.005788121870526659
Discriminação dos principais resultados:
mitigated: o valor esperado do QESEM totalmente mitigado.unmitigated: o resultado bruto do ruído físico sem mitigação de erros.
Resultados da extrapolação heurística do QESEM
Em uma execução padrão do QESEM com um único precision flutuador, os resultados também incluem pontos de escala de ruído disponíveis automaticamente, que são utilizados para a heurística do QESEM. Esses pontos são calculados sem recursos adicionais da QPU.
A escala 1.0 representa o nível de ruído do dispositivo físico com mitigação de leitura (REM), enquanto a escala 2.0 corresponde ao ponto complementar com amplificação de ruído, também com REM. Esses pontos são utilizados para gerar o qesem_heuristic resultado.
qesem_heuristic: uma estimativa do tipo ZNE calculada a partir dos dados disponíveis, ajustados em função do ruído. Atualmente, isso utiliza extrapolação exponencial.noise_scaling.results_with_REM: valores esperados em diferentes escalas de ruído, todos com mitigação de leitura (REM).
Um detalhe sutil, mas importante, é que o resultado da escala 1.0 não é o mesmo que o unmitigated resultado. Ambos correspondem ao nível de ruído do dispositivo físico, mas o ponto da escala 1.0 inclui a mitigação da leitura, enquanto unmitigated não inclui.
print("QESEM heuristic results:")
for pub_idx, pub_result in enumerate(sample_result):
print(f"\nPUB {pub_idx}:")
for circ_idx, circ_results in enumerate(pub_result.metadata["results"]):
print(f" Circuit {circ_idx}:")
for obs_idx, (obs_array, result_dict) in enumerate(circ_results):
print(f" Observable {obs_idx}: {obs_array}")
qesem_heuristic = result_dict["qesem_heuristic"][0]
print(" QESEM heuristic:")
print(
f" Value: {qesem_heuristic['value']} ± {qesem_heuristic['error_bar']}"
)
print(
f" Extrapolation: {qesem_heuristic['extrapolation']}"
)
print(
f" Scale factors: {qesem_heuristic['scale_factors']}"
)
noise_scaling = result_dict["noise_scaling"]
print(" Noise scaling results:")
print(
f" Scaling method: {noise_scaling['scaling_method']}"
)
print(" Results with Readout mitigation (REM):")
for rem_result in sorted(
(
item
for item in noise_scaling["results_with_REM"]
if item["scale"] != 0.0
),
key=lambda item: item["scale"],
):
print(
f" Scale factor {rem_result['scale']}: {rem_result['value']} ± {rem_result['error_bar']}"
)Output:
QESEM heuristic results:
PUB 0:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM heuristic:
Value: 1.0008161638888535 ± 0.0038859458884403964
Extrapolation: exponential
Scale factors: [1.0, 2.0]
Noise scaling results:
Scaling method: QESEM
Results with Readout mitigation (REM):
Scale factor 1.0: 0.9918395459270772 ± 0.0012565417579355634
Scale factor 2.0: 0.982943441922748 ± 0.0028919278067695018
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM heuristic:
Value: 0.9960853148925298 ± 0.013811635038961175
Extrapolation: exponential
Scale factors: [1.0, 2.0]
Noise scaling results:
Scaling method: QESEM
Results with Readout mitigation (REM):
Scale factor 1.0: 0.9902860583785115 ± 0.005921236914723409
Scale factor 2.0: 0.984520565414274 ± 0.006909522262347639
Os exemplos a seguir se concentram em entradas e resultados específicos de cada recurso; portanto, não exibem todas as métricas de execução a cada vez. Os metadados de nível superior mostrados anteriormente, como total_qpu_time, gate_fidelities, total_chutes, medidas_de_mitigação e uso_de_recursos, também estão disponíveis para esses trabalhos.
Algumas variáveis dos exemplos anteriores, incluindo o backend, os observáveis e os parâmetros do circuito base, são reutilizadas a seguir para maior concisão.
Todos os exemplos a seguir também podem ser executados com estimativa empírica de tempo. Para ativá-lo, passe <code>"estimate_time_only": "empírico"</code> nas opções da função.
Exemplo de circuito parametrizado
Muitos algoritmos avaliam o mesmo circuito com vários valores de parâmetros. O envio do circuito parametrizado como um único trabalho no QESEM permite que o QESEM compartilhe a caracterização e a calibração entre as instâncias do circuito, o que pode reduzir a sobrecarga de tempo de QPU em comparação com a execução de trabalhos separados.
Para enviar um circuito parametrizado, é necessário utilizar o "minimal_with_layout_opt" nível de transpilação.
Os circuitos enviados neste nível já devem estar expressos utilizando as portas básicas do backend, dependendo do backend. Nesse nível, o QESEM mantém a estrutura enviada o mais próxima possível do circuito de entrada, respeita as barreiras durante a estratificação (agrupamento de operações em camadas de portas paralelas de dois qubits) e ainda lida automaticamente com o mapeamento de hardware para qubits de alta fidelidade e com a conectividade dos dispositivos.
Na prática, isso significa que você deve transpilá-los para as portas básicas do backend de destino antes do envio. Segue abaixo um exemplo simples de transpilagem de porta de base.
Atualmente, o QESEM suporta apenas uma variável observável por conjunto de parâmetros. As duas linhas de parâmetros abaixo estão associadas aos dois observáveis: a primeira linha é medida com avg_magnetization, e a segunda linha é medida com other_observable.
# Transpile to the backend basis gates only. With minimal_with_layout_opt, QESEM handles hardware mapping/connectivity and observable layout internally.
from qiskit_ibm_runtime.fake_provider import FakeFez
backend = FakeFez()
basis = backend.operation_names
print(basis)
param0 = qiskit.circuit.Parameter("param0")
param1 = qiskit.circuit.Parameter("param1")
parametrized_circ = qiskit.QuantumCircuit(5)
parametrized_circ.rx(param0, 0)
parametrized_circ.rx(param1, 1)
parametrized_circ.cx(0, 1)
parametrized_circ.cx(2, 3)
parametrized_circ.cx(1, 2)
parametrized_circ.cx(3, 4)
parametrized_circ = qiskit.transpile(
parametrized_circ, basis_gates=basis, optimization_level=1
)
parametrized_parameter_values = [[0.5, 0.1], [0.0, 0.6]]
parametrized_observables = [avg_magnetization, other_observable]
parametrized_job = qesem_function.run(
pubs=[
(
parametrized_circ,
parametrized_observables,
parametrized_parameter_values,
0.1,
)
],
backend_name=backend_name,
options={
"max_execution_time": 300,
"transpilation_level": "minimal_with_layout_opt",
},
)print(parametrized_job.job_id)
print(parametrized_job.status())Output:
d1b0e29b-196c-4896-aec6-44a268ebd874
DONE
parametrized_result = parametrized_job.result()print("Parameterized circuit QESEM results:")
for pub_idx, pub_result in enumerate(parametrized_result):
print(f"\nPUB {pub_idx}:")
print(f" Mitigated expectation values: {pub_result.data.evs}")
print(f" Mitigated error bars: {pub_result.data.stds}")
noisy_results = pub_result.metadata["noisy_results"]
print(f" Unmitigated expectation values: {noisy_results.evs}")
print(f" Unmitigated error bars: {noisy_results.stds}")
print(" Results for each parameter value:")
for param_idx, param_results in enumerate(pub_result.metadata["results"]):
print(
f" Parameter set {param_idx}: {parametrized_parameter_values[param_idx]}"
)
for obs_idx, (obs_array, result_dict) in enumerate(param_results):
print(f" Observable {obs_idx}: {obs_array}")
print(
f" QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}"
)
print(
f" Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}"
)Output:
Parameterized circuit QESEM results:
PUB 0:
Mitigated expectation values: [0.92392021 0.82517653]
Mitigated error bars: [0.00565281 0.00616016]
Unmitigated expectation values: [0.9028 0.78771429]
Unmitigated error bars: [0.00335142 0.00925413]
Results for each parameter value:
Parameter set 0: [0.5, 0.1]
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 0.923920210615709 ± 0.005652811570890183
Unmitigated value: 0.9028 ± 0.0033514176105045447
Parameter set 1: [0.0, 0.6]
Observable 0: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 0.8251765289285893 ± 0.006160161743353999
Unmitigated value: 0.7877142857142858 ± 0.009254130564027902
Exemplo de “multi-pub”
A execução em múltiplos pubs é útil quando se deseja executar vários circuitos relacionados em um único trabalho do QESEM. Assim como a execução parametrizada, isso pode reduzir a sobrecarga, pois o QESEM pode compartilhar a caracterização e a calibração entre instâncias do circuito, em vez de repeti-las em tarefas separadas.
Isso é especialmente útil para circuitos com uma estrutura de camadas compartilhadas, como cargas de trabalho do tipo Trotter, nas quais diferentes circuitos reutilizam as mesmas camadas únicas. Nesse caso, a execução conjunta dessas análises pode reduzir o custo da caracterização em comparação com trabalhos independentes de QESEM.
Trabalhos com publicação em vários veículos exigem "transpilation_level": "minimal_with_layout_opt". Assim como no exemplo parametrizado, os circuitos devem ser transpilados para as portas básicas do backend de destino antes do envio. O QESEM, então, lida internamente com a conectividade dos dispositivos, o layout e o mapeamento para qubits de alta fidelidade.
Cada PUB abaixo contém um circuito e os mesmos dois observáveis usados anteriormente neste notebook; portanto, o resultado retornado PrimitiveResult contém um PubResult por circuito de entrada.
O exemplo abaixo utiliza dois circuitos de Trotter simples com o mesmo padrão de camadas: circ_a possui uma camada de Trotter, e circ_b repete o mesmo padrão de camadas duas vezes. Isso torna a estrutura compartilhada explícita.
def make_trotter_circuit(num_qubits, num_layers, zz_angle=0.2, x_angle=0.1):
trotter_circ = qiskit.QuantumCircuit(num_qubits)
for _ in range(num_layers):
for q in range(num_qubits):
trotter_circ.rx(x_angle, q)
trotter_circ.barrier()
for q in range(0, num_qubits - 1, 2):
trotter_circ.rzz(zz_angle, q, q + 1)
trotter_circ.barrier()
for q in range(1, num_qubits - 1, 2):
trotter_circ.rzz(zz_angle, q, q + 1)
trotter_circ.barrier()
return trotter_circ
circ_a = make_trotter_circuit(num_qubits=5, num_layers=1)
circ_b = make_trotter_circuit(num_qubits=5, num_layers=2)multi_pubs = [
(
qiskit.transpile(qci, basis_gates=basis, optimization_level=1),
[avg_magnetization, other_observable],
)
for qci in [circ_a, circ_b]
]
multi_circ_job = qesem_function.run(
pubs=multi_pubs,
backend_name=backend_name,
options={
"max_execution_time": 300,
"transpilation_level": "minimal_with_layout_opt",
"default_precision": 0.1,
},
)print(multi_circ_job.job_id)
print(multi_circ_job.status())Output:
e34565b8-7262-4133-a120-de42ce624a99
DONE
multi_circ_result = multi_circ_job.result()print("Multi-pub QESEM results:")
for pub_idx, pub_result in enumerate(multi_circ_result):
print(f"\nPUB {pub_idx}:")
print(f" Mitigated expectation values: {pub_result.data.evs}")
print(f" Mitigated error bars: {pub_result.data.stds}")
noisy_results = pub_result.metadata["noisy_results"]
print(f" Unmitigated expectation values: {noisy_results.evs}")
print(f" Unmitigated error bars: {noisy_results.stds}")
print(" Results for each observable:")
for circ_idx, circ_results in enumerate(pub_result.metadata["results"]):
print(f" Circuit {circ_idx}:")
for obs_idx, (obs_array, result_dict) in enumerate(circ_results):
print(f" Observable {obs_idx}: {obs_array}")
print(
f" QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}"
)
print(
f" Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}"
)Output:
Multi-pub QESEM results:
PUB 0:
Mitigated expectation values: [0.99502406 1.02209332]
Mitigated error bars: [0.00483819 0.00707488]
Unmitigated expectation values: [0.96934286 0.97271429]
Unmitigated error bars: [0.00124855 0.00617294]
Results for each observable:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 0.9950240647925642 ± 0.004838188086259301
Unmitigated value: 0.9693428571428573 ± 0.0012485470362492692
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 1.0220933230604674 ± 0.007074884384355636
Unmitigated value: 0.9727142857142859 ± 0.006172939375512439
PUB 1:
Mitigated expectation values: [0.98850017 1.02555188]
Mitigated error bars: [0.0077912 0.01672652]
Unmitigated expectation values: [0.93682857 0.95371429]
Unmitigated error bars: [0.00156245 0.00665735]
Results for each observable:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
QESEM mitigated value: 0.988500171577252 ± 0.007791203181151346
Unmitigated value: 0.9368285714285716 ± 0.001562451883089579
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
QESEM mitigated value: 1.02555188098689 ± 0.016726524388086233
Unmitigated value: 0.9537142857142858 ± 0.006657345655544263
Exemplo de Ajuste de Erro Quase-Probabilístico (QET)
O Ajuste de Erro Quase-Probabilístico (QET) solicita valores esperados em fatores de escala de ruído selecionados. Isso é útil para estudos de escalonamento de ruído personalizados e fluxos de trabalho de extrapolação com ruído zero. A escala 1.0 representa o nível físico de ruído; valores entre 0.0 e 1.0 reduzem parcialmente o ruído, enquanto valores acima de 1.0 amplificam o ruído.
Para usar o QET com a função Qiskit, passe um dicionário como a precisão do PUB. O dicionário mapeia cada escala de ruído solicitada para sua precisão alvo. Os resultados do fator de escala retornados são armazenados em noise_scaling.results_with_REM e incluem a mitigação da leitura. O ponto na escala 1.0 , portanto, não é idêntico ao valor não mitigado, pois 1.0 inclui a mitigação da leitura, enquanto unmitigated não inclui.
Quando uma escala é solicitada, o QESEM também retorna a escala complementar em torno de 1.0 sem consumo adicional de QPU. Por exemplo, a solicitação 0.5 de também pode retornar 1.5, e a solicitação 1.3 de também pode retornar 0.7. A precisão na escala complementar não é garantida.
noise_scale_precision = {0.5: 0.15, 1.3: 0.2}
qet_job = qesem_function.run(
pubs=[
(
circ,
[avg_magnetization, other_observable],
None,
noise_scale_precision,
)
],
backend_name=backend_name,
options={"max_execution_time": 300},
)print(qet_job.job_id)
print(qet_job.status())Output:
8195fa58-f037-4651-8715-36ce1cdc5521
DONE
qet_result = qet_job.result()print("QET noise-scaling results:")
for pub_idx, pub_result in enumerate(qet_result):
print(f"\nPUB {pub_idx}:")
noisy_results = pub_result.metadata["noisy_results"]
print(f" Unmitigated expectation values: {noisy_results.evs}")
print(f" Unmitigated error bars: {noisy_results.stds}")
print(" Results for each observable:")
for circ_idx, circ_results in enumerate(pub_result.metadata["results"]):
print(f" Circuit {circ_idx}:")
for obs_idx, (obs_array, result_dict) in enumerate(circ_results):
print(f" Observable {obs_idx}: {obs_array}")
noise_scaling = result_dict["noise_scaling"]
print(
f" Scaling method: {noise_scaling['scaling_method']}"
)
print(" Results with Readout mitigation (REM):")
for rem_result in sorted(
(
item
for item in noise_scaling["results_with_REM"]
if item["scale"] != 0.0
),
key=lambda item: item["scale"],
):
print(
f" Scale factor {rem_result['scale']}: {rem_result['value']} ± {rem_result['error_bar']}"
)Output:
QET noise-scaling results:
PUB 0:
Unmitigated expectation values: [0.97822857 0.96171429]
Unmitigated error bars: [0.00123812 0.00672958]
Results for each observable:
Circuit 0:
Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())
Scaling method: QESEM
Results with Readout mitigation (REM):
Scale factor 0.5: 0.9938730340199383 ± 0.0032116907357568275
Scale factor 0.7: 0.9963976191853445 ± 0.00036300258869586616
Scale factor 1.0: 0.9898115079506586 ± 0.0012525947426560995
Scale factor 1.3: 0.9864667065580341 ± 0.002633221613518526
Scale factor 1.5: 0.9838755527197551 ± 0.002948417797996015
Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())
Scaling method: QESEM
Results with Readout mitigation (REM):
Scale factor 0.5: 1.0006538544450332 ± 0.002121742014777343
Scale factor 0.7: 1.0004159801523036 ± 0.0021671375357823794
Scale factor 1.0: 0.9898058846339917 ± 0.00690183710903159
Scale factor 1.3: 0.9948946719997267 ± 0.002146532859610311
Scale factor 1.5: 0.9927220368192772 ± 0.0020875057190323882
Buscar mensagens de erro
Se o status da sua carga de trabalho for ERROR, use job.result() para obter a mensagem de erro da seguinte maneira:
# Get the result and truncate for readability
result = sample_job.result()
result_str = str(result)
max_length = 500 # Adjust this value as necessary
if len(result_str) > max_length:
truncated = (
result_str[:max_length]
+ f"... (truncated {len(result_str) - max_length} characters)"
)
else:
truncated = result_str
print(truncated)Output:
PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(2,), dtype=float64>), stds=np.ndarray(<shape=(2,), dtype=float64>), shape=(2,)), metadata={'gate_fidelities': {'CZ': 0.9979444718552628, 'ID1Q': 0.9991994239814883}, 'total_shots': 498600, 'mitigation_shots': 223400, 'transpiled_circs': [{'circuit': 'OPENQASM 3.0;\ninclude "stdgates.inc";\nbit[76] c0;\nqubit[76] q0;\nrx(0) q0[54];\nrx(0) q0[59];\nrx(0) q0[75];\nrz(pi/2) q0[54];\nrz(pi/2) q0[59];\nrz(pi/2) q0[75];\nrx(pi/2) q0[54];\nr... (truncated 3771 characters)
Obtenha suporte
A equipe de suporte da Qedma está aqui para ajudar! Se você encontrar algum problema ou tiver dúvidas sobre o uso da função Qiskit da QESEM, não hesite em entrar em contato. Nossa equipe de suporte experiente e amigável está pronta para ajudá-lo com qualquer dúvida técnica ou questionamento que você possa ter.
Você pode nos enviar um e-mail para [email protected] para obter assistência. Inclua o máximo de detalhes possível sobre o problema que está enfrentando para nos ajudar a fornecer uma resposta rápida e precisa. Você também pode entrar em contato com seu representante POC dedicado da Qedma por e-mail ou telefone.
Para nos ajudar a ajudá-lo de forma mais eficiente, forneça as seguintes informações ao entrar em contato conosco:
- Uma descrição detalhada do problema
- O ID da tarefa
- Quaisquer mensagens ou códigos de erro relevantes
Temos o compromisso de fornecer suporte imediato e eficaz para garantir que você tenha a melhor experiência possível com a nossa função Qiskit.
Estamos sempre buscando melhorar nosso produto e agradecemos suas sugestões! Se você tiver ideias sobre como podemos melhorar nossos serviços ou recursos que gostaria de ver, envie-nos suas sugestões para [email protected].
Próximas etapas
- Solicite acesso ao Qedma QESEM.
- Consulte a referência da API para esta função do Qiskit.
- Experimente o tutorial “Simulação de um modelo de Ising de campo inclinado com 2D ” utilizando a função QESEM.
- Revisão Aharonov, D., et al. (2025). Mitigação de erros confiável e de alta precisão para circuitos quânticos em escala utilitária. arXiv pré-impressão arXiv:2508.10997.
- Resenha Aharonov, D., et al. (2025). Mitigação de erros lógicos com reconhecimento da síndrome. arXiv pré-impressão arXiv:2508.10997.
- Resenha Aharonov, D., et al. (2025). Sobre a importância da mitigação de erros na computação quântica. arXiv pré-impressão arXiv:2512.23810.
- Revisão Bauman, N. P., et al. (2025). Teoria do Downfolding de Clusters Acoplados em Simulações de Sistemas Químicos em Hardware Quântico. arXiv pré-impressão arXiv:2507.01199.
- Resenha Goldack, M., et al. (2026). Cálculo de propriedades estatísticas de campos de velocidade em hardware quântico atual. arXiv pré-impressão arXiv:2601.10166.
- Resenha Sakuma, R., et al. (2026). Análise da simetria de grupos pontuais de funções de onda com muitos elétrons em um computador quântico arXiv pré-impressão arXiv:2605.24824.