Solucionador de otimização: uma função Qiskit da Q-CTRL Fire Opal
Consulte a referência da API
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.
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-ibm-runtime~=0.47.0 sympy~=1.14.0
Visão geral
Com o Fire Opal Optimization Solver, você pode resolver problemas de otimização em escala de serviços públicos em hardware quântico sem precisar de conhecimento quântico. Basta inserir a definição do problema de alto nível, e o Solver se encarrega do resto. Todo o fluxo de trabalho é sensível a ruídos e aproveita o Fire Opal's Performance Management. O Solver fornece de forma consistente soluções precisas para problemas classicamente desafiadores, mesmo em escala de dispositivo completo nas maiores QPUs IBM®.
O Solver é flexível e pode ser utilizado para resolver problemas de otimização combinatória definidos como funções-objetivo ou grafos arbitrários. Os problemas não precisam ser mapeados para a topologia do dispositivo. Tanto os problemas sem restrições quanto os com restrições são solucionáveis, desde que as restrições possam ser formuladas como termos de penalidade. Os exemplos incluídos neste guia demonstram como resolver um problema de otimização em escala de utilidade, com e sem restrições, utilizando diferentes tipos de entrada do Solver. O primeiro exemplo trata de um problema de corte máximo definido em um grafo regular de grau 3 com 156 vértices, enquanto o segundo exemplo aborda um problema de cobertura mínima de vértices com 50 vértices, definido por uma função de custo.
Para obter acesso ao Optimization Solver, entre em contato com a Q-CTRL.
Descrição da função
O Solver otimiza e automatiza totalmente o algoritmo inteiro, desde a supressão de erros no nível do hardware até o mapeamento eficiente do problema e a otimização clássica de loop fechado. Nos bastidores, o pipeline do Solver reduz os erros em todos os estágios, possibilitando o desempenho aprimorado necessário para um dimensionamento significativo. O fluxo de trabalho subjacente é inspirado no Algoritmo de Otimização Aproximada Quântica (QAOA), que é um algoritmo híbrido quântico-clássico. Para obter um resumo detalhado do fluxo de trabalho completo do Optimization Solver, consulte o manuscrito publicado.
Para resolver um problema genérico com o Optimization Solver:
- Defina seu problema como uma função objetiva, um gráfico ou uma cadeia de spin
SparsePauliOp. - Conecte-se à função por meio do Qiskit Functions Catalog.
- Execute o problema com o Solver e recupere os resultados.
Formatos de problemas aceitos
- Representação de expressão polinomial de uma função objetiva. Idealmente criado em Python com um objeto SymPy Poly existente e formatado em uma string usando sympy.srepr.
- Representação gráfica de um tipo específico de problema. O gráfico deve ser criado usando a biblioteca networkx em Python. Em seguida, ele deve ser convertido em uma string usando a função networkx
[nx.readwrite.json_graph.adjacency_data](http://nx.readwrite.json_graph.adjacency_data.). - Representação da cadeia de spin de um problema específico. A cadeia de spin deve ser representada como um objeto
SparsePauliOp; consulte a documentação para obter mais detalhes.
Se você quiser usar um backend que esta função ainda não suporta, entre em contato com a Q-CTRL para solicitar a adição desse suporte.
Referências
Os resultados de benchmarking publicados mostram que o Solver resolve com sucesso problemas com mais de 120 qubits, superando até mesmo os resultados publicados anteriormente sobre recozimento quântico e dispositivos de íons presos. As métricas de referência a seguir fornecem uma indicação aproximada da precisão e do dimensionamento dos tipos de problemas com base em alguns exemplos. As métricas reais podem diferir com base em vários recursos do problema, como o número de termos na função objetiva (densidade) e sua localidade, número de variáveis e ordem polinomial.
O "Número de qubits" indicado não é uma limitação rígida, mas representa limites aproximados em que você pode esperar uma precisão de solução extremamente consistente. Problemas de tamanhos maiores foram resolvidos com sucesso, e os testes além desses limites são incentivados.
A conectividade arbitrária de qubit é suportada em todos os tipos de problemas.
Tipo de problema | Número de qubits | Exemplo | Precisão | Tempo Total (s) | Uso do tempo de execução (s) | Número de iterações |
|---|---|---|---|---|---|---|
| Problemas quadráticos com conexões esparsas | 156 | 3-corte máximo regular | 100% | 1764 | 293 | 16 |
| Otimização binária de ordem superior | 156 | Modelo de vidro de spin de Ising | 100% | 1461 | 272 | 16 |
| Problemas quadráticos densamente conectados | 50 | Corte máximo com conexão total | 100% | 1758 | 268 | 12 |
| Problema restrito com termos de penalidade | 50 | Cobertura mínima ponderada de vértices com 8% de densidade de bordas | 100% | 1074 | 215 | 22 |
Introdução
Primeiro, autentique-se usando sua chave de API IBM Quantum. Em seguida, selecione a função do Qiskit da seguinte maneira. (Este trecho pressupõe que você já tenha salvo sua conta no seu ambiente local.)
from qiskit_ibm_catalog import QiskitFunctionsCatalog
catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# Verify that you have access to the function
catalog.list()Output:
[QiskitFunction(qunova/hivqe-chemistry),
QiskitFunction(global-data-quantum/quantum-portfolio-optimizer),
QiskitFunction(algorithmiq/tem),
QiskitFunction(qedma/qesem),
QiskitFunction(multiverse/singularity),
QiskitFunction(ibm/circuit-function),
QiskitFunction(q-ctrl/optimization-solver),
QiskitFunction(colibritd/quick-pde),
QiskitFunction(q-ctrl/performance-management),
QiskitFunction(kipu-quantum/iskay-quantum-optimizer)]
# Access Function
solver = catalog.load("q-ctrl/optimization-solver")Exemplo: Otimização sem restrições
Resolva o problema do corte máximo (max-cut). O exemplo a seguir demonstra as capacidades do Solver em um problema de corte máximo em um grafo não ponderado de 156 nós e 3 arcos regulares, mas também é possível resolver problemas em grafos ponderados.
Além do qiskit-ibm-catalog, você também usará os seguintes pacotes para executar este exemplo: networkx e numpy. Você pode instalar esses pacotes descomentando a célula a seguir se estiver executando este exemplo em um notebook usando o kernel IPython.
# %pip install networkx numpy1. Defina o problema
Você pode resolver um problema de corte máximo definindo um problema de grafos e especificando problem_type='maxcut'.
import networkx as nx
import numpy as np
# Generate a random graph with 156 nodes
maxcut_graph = nx.random_regular_graph(d=3, n=156, seed=8)# Optionally, visualize the graph
nx.draw_networkx(
maxcut_graph, nx.kamada_kawai_layout(maxcut_graph), node_size=100
)Output:
O Solver aceita uma string como entrada de definição do problema.
# Convert graph to string
problem_as_str = nx.readwrite.json_graph.adjacency_data(maxcut_graph)2. Execute o problema
Ao usar o método de entrada baseado em gráficos, especifique o tipo de problema.
# Solve the problem
maxcut_job = solver.run(
problem=problem_as_str,
problem_type="maxcut",
backend_name=backend_name, # E.g. "ibm_fez"
)Verifique o status da sua carga de trabalho do Qiskit Function ou obtenha os resultados da seguinte maneira:
# Print the ID so you can use it later, if necessary
print(maxcut_job.job_id)
# Get job status
print(maxcut_job.status())Output:
34b53970-d95a-4e24-8763-fc6f3d112843
QUEUED
3. Recuperar o resultado
Recupere o valor de corte ideal do dicionário de resultados.
O mapeamento das variáveis para a cadeia de bits pode ter mudado. O dicionário de saída contém um variables_to_bitstring_index_map subdicionário, que ajuda a verificar a ordem.
# Poll for results
maxcut_result = maxcut_job.result()
# Take the absolute value of the solution since the cost function is minimized
qctrl_maxcut = abs(maxcut_result["solution_bitstring_cost"])
# Print the optimal cut value found by the Optimization Solver
print(f"Optimal cut value: {qctrl_maxcut}")Output:
Optimal cut value: 210.0
Você pode verificar a precisão do resultado resolvendo o problema de forma clássica com solucionadores de código aberto, como PuLP se o gráfico não for densamente conectado. Problemas de alta densidade podem exigir solucionadores clássicos avançados para validar a solução.
Exemplo: Otimização restrita
O exemplo anterior de max-cut é um problema comum de otimização binária quadrática sem restrições. O Solucionador de Otimização do Q-CTRL pode ser utilizado para diversos tipos de problemas, incluindo otimização com restrições. É possível resolver tipos arbitrários de problemas inserindo a definição do problema representada como um polinômio, no qual as restrições são modeladas como termos de penalidade.
O exemplo a seguir demonstra como construir uma função de custo para um problema de otimização restrito, cobertura mínima de vértices (MVC).
Além dos pacotes qiskit-ibm-catalog e qiskit , você também usará os seguintes pacotes para executar este exemplo: numpy, networkx, e sympy. Você pode instalar esses pacotes descomentando a célula a seguir se estiver executando este exemplo em um notebook usando o kernel IPython.
# %pip install numpy networkx sympy1. Defina o problema
Defina um problema de MVC aleatório gerando um gráfico com nós ponderados aleatoriamente.
import networkx as nx
from sympy import symbols, Poly, srepr
# To change the weights, change the seed to any integer.
rng_seed = 18
_rng = np.random.default_rng(rng_seed)
node_count = 50
edge_probability = 0.08
mvc_graph = nx.erdos_renyi_graph(
node_count, edge_probability, seed=rng_seed, directed=False
)
# add node weights
for i in mvc_graph.nodes:
mvc_graph.add_node(i, weight=_rng.random())
# Optionally, visualize the graph
nx.draw_networkx(mvc_graph, nx.kamada_kawai_layout(mvc_graph), node_size=200)Output:
Um modelo de otimização padrão para MVC ponderado pode ser formulado da seguinte forma. Primeiro, uma penalidade deve ser adicionada para qualquer caso em que uma borda não esteja conectada a um vértice no subconjunto. Portanto, deixe se o vértice estiver na cobertura (ou seja, no subconjunto) e caso contrário. Em segundo lugar, o objetivo é minimizar o número total de vértices no subconjunto, que pode ser representado pela seguinte função:
# Construct the cost function.
variables = symbols([f"n[{i}]" for i in range(node_count)])
cost_function = Poly(0, variables)
for i in mvc_graph.nodes():
weight = mvc_graph.nodes[i].get("weight", 0)
cost_function += variables[i] * weightAgora, cada borda do gráfico deve incluir pelo menos um ponto final da cobertura, o que pode ser expresso como a desigualdade:
Qualquer caso em que uma borda não esteja conectada ao vértice de cobertura deve ser penalizado. Isso pode ser representado na função de custo adicionando uma penalidade no formato , em que é uma constante de penalidade positiva. Portanto, uma alternativa sem restrições para a desigualdade com restrições para o MVC ponderado é:
# Add penalty term.
penalty_constant = 2
for i, j in mvc_graph.edges():
cost_function += penalty_constant * (
1 - variables[i] - variables[j] + variables[i] * variables[j]
)2. Execute o problema
# Solve the problem
mvc_job = solver.run(
problem=srepr(cost_function),
backend_name=backend_name, # E.g. "ibm_fez"
)Verifique o status da sua carga de trabalho do Qiskit Function ou obtenha os resultados da seguinte maneira:
print(mvc_job.status())Output:
QUEUED
3. Obtenha o resultado
Recupere a solução e analise os resultados. Como esse problema tem nós ponderados, a solução não é simplesmente o número mínimo de nós cobertos. Em vez disso, o custo da solução representa a soma dos pesos dos vértices que estão incluídos na cobertura do vértice. Ele representa o "custo" ou "peso" total de cobrir todas as bordas do gráfico usando os vértices selecionados.
mvc_result = mvc_job.result()
qctrl_cost = mvc_result["solution_bitstring_cost"]
# Print results
print(f"Solution cost: {qctrl_cost}")Output:
Solution cost: 10.248198273708624
Obtenha suporte
Em caso de dúvidas ou problemas, entre em contato com a Q-CTRL.
Log de mudanças
- 11/02/2026: Agora oferecemos suporte para
ibm_miami
Próximas etapas
- Solicite acesso ao Solucionador de Otimização Q-CTRL.
- Consulte a referência da API para esta função do Qiskit.
- Experimente o tutorial Solve higher-order binary optimization problems with Q-CTRL's Optimization Solver.
- Revisão Sachdeva, N., et al. (2024). A otimização quântica usando um computador quântico de 127 qubits com modelo de porta IBM pode superar os annealers quânticos em problemas de otimização binária não triviais. arXiv pré-impressão arXiv:2406.01743.
- Revisão Loco, D., et al. (2026). Previsão prática do local de hidratação do bolso proteico para a descoberta de medicamentos em um computador quântico. arXiv pré-impressão arXiv:2512.08390.
- Analise o estudo de caso da Mazda.
- Analise o estudo de caso da Network Rail.
- Analise o estudo de caso do Exército Australiano.
- Analise o estudo de caso da Transport for New South Wales.