Optimizador cuántico con restricciones: una función de Qiskit desarrollada por Aqarios
Consulta la referencia de la API
Qiskit Functions Son una función experimental disponible únicamente para los usuarios de los planes « IBM Quantum® Premium Plan », «Flex Plan» y « On-Prem » (a través de la API de IBM Quantum Platform ). Se encuentran en fase de versión preliminar y están sujetas a cambios.
Visión general
Con el «Constrained Quantum Optimizer» de Aqarios, puedes resolver problemas de optimización binaria con restricciones en hardware cuántico d IBM®, sin necesidad de reformulación manual ni mapeo de circuitos. Solo tienes que proporcionar un problema en formato de archivo LP, MPS o Luna Model. La función se encarga automáticamente de la reformulación, la síntesis de circuitos, la transpilación y la ejecución en hardware. El solucionador utiliza el método iterativo de «warm-starting» [1] del algoritmo « FlexQAOA », una extensión nativa de restricciones del algoritmo cuántico de optimización aproximada (QAOA).
El optimizador está diseñado para resolver problemas binarios con restricciones. En concreto, las restricciones «one-hot» y las restricciones de empaquetamiento de conjuntos pueden aplicarse de forma nativa mediante el uso de mezcladores XY. Otros tipos de restricciones se reformulan automáticamente como términos de penalización.
Descripción
El rendimiento puede depender tanto de la instancia del problema como de los pasos de procesamiento posteriores. En algunos casos, las muestras clásicas y las generadas cuánticamente podrían alcanzar una calidad final de solución similar tras un posprocesamiento equivalente. Por lo tanto, la evaluación debería tener en cuenta todo el flujo de trabajo de optimización.
El optimizador cuántico con restricciones implementa el algoritmo QAOA con mezclador XY iterativo y arranque en caliente (IWS-QAOA) [1]. El algoritmo ejecuta circuitos QAOA de ángulo fijo en hardware cuántico y actualiza las probabilidades iniciales de «warm-start» de cada circuito utilizando los resultados de las mediciones de la iteración anterior. No es necesario entrenar ningún parámetro variacional; en su lugar, se elige una parametrización de rampa lineal fija.
Al utilizar mezcladores XY para aplicar restricciones «one-hot», se puede mejorar drásticamente la calidad de la solución en problemas con restricciones, ya que el espacio de búsqueda se reduce prácticamente a un subespacio factible más pequeño, sin que se introduzca ninguna complejidad adicional —debida a los términos de penalización— en el paisaje de optimización.
Flujo de trabajo
A continuación se describe el flujo de trabajo de la función:
- Preprocesamiento : Antes de la síntesis del circuito, el optimizador analiza la estructura de restricciones del problema de entrada:
- Preprocesamiento de grafos: cuando resulta aplicable al problema, este se analiza como un grafo, en el que las aristas determinan la relación entre las variables. Este análisis de gráficos permite introducir dos mejoras en el tratamiento previo de los problemas. En primer lugar, las restricciones individuales pueden agruparse en una sola restricción de mayor envergadura mediante la fusión de cliques, de modo que queden representadas por un único mezclador XY. En segundo lugar, las variables que solo tienen un vecino pueden fijarse de forma determinista, lo que reduce el tamaño y la complejidad del problema.
- Resolución de restricciones: El preprocesador gestiona cada restricción por separado: si la restricción es del tipo «one-hot», puede aplicarse mediante mezcladores XY. Si se trata de una restricción de empaquetamiento de conjuntos, primero se transformará en una restricción de tipo «one-hot». Las restricciones de igualdad se gestionan mediante penalizaciones cuadráticas, y las restricciones de desigualdad, mediante penalización desequilibrada.
- Derivación de la penalización: Las restricciones que no pueden expresarse como restricciones de igualdad «one-hot» se convierten en términos de penalización. El optimizador deduce automáticamente la intensidad de la penalización a partir de la estructura del problema.
- Inicio en caliente iterativo : el optimizador ejecuta varias cadenas de inicio en caliente en paralelo. Cada cadena contiene una distribución de probabilidad sobre las asignaciones de variables, que se utiliza como probabilidad inicial del circuito QAOA (estado de arranque en caliente). En cada iteración, una cadena toma muestras del circuito cuántico, aplica un posprocesamiento clásico y actualiza su distribución en función de la aparición de las muestras. A lo largo de las iteraciones, esto centra la búsqueda en soluciones de alta calidad sin necesidad de un bucle de optimización variacional.
El número de cadenas (num_parallel), el presupuesto total de disparos por cadena (total_shots) y el número de repeticiones de QAOA (reps) son los principales parámetros que permiten equilibrar la calidad de la solución y el tiempo de ejecución.
Referencias comparativas
Las pruebas comparativas que se muestran a continuación demuestran que la función «Constrained Quantum Optimizer» de Qiskit es capaz de encontrar soluciones viables y de alta calidad para problemas de optimización con restricciones que cuentan con más de 100 variables binarias. La precisión es la relación entre el valor objetivo obtenido y el valor óptimo conocido. El tiempo de ejecución es el tiempo real transcurrido desde la invocación de la función hasta la entrega del resultado. El uso de la QPU es el tiempo de computación cuántica facturable.
Se analizaron dos problemas: el problema del conjunto independiente máximo (MIS) y el «Max- -Cut», que es una extensión del conocido problema « MaxCut » a más de dos categorías. El problema de «Max- -Cut» es también el problema de optimización equivalente al problema de decisión de coloración de grafos (cuando se cortan todas las aristas, el grafo es « -colorable»).
Problema | Variables | Restricciones | Qubits | Precisión | Viabilidad | Tiempo total de ejecución (s) | Uso de la CPU (s) | Total de tiros |
|---|---|---|---|---|---|---|---|---|
| MIS es60fst02 | 186 | 280 | 124 | 100.0% | Sí | 940.2 | 147.0 | 25.0k |
| MIS sloane_2dc_128 | 128 | 5173 | 74 | 100.0% | Sí | 347.6 | 106.0 | 12.5k |
| Max-3-Cut Club de kárate | 99 | 33 | 99 | 98.7% | Sí | 279.5 | 166.0 | 25.0k |
| Max-4-Cut Club de kárate | 132 | 33 | 132 | 100.0% | Sí | 258.3 | 200.0 | 25.0k |
Notas sobre las pruebas de referencia
- Los resultados anteriores se obtuvieron en el procesador Heron
ibm_marrakeshr2 con las opciones predeterminadas y la funciónuse_sessionactivada. Por ejemplosloane_2dc_128,total_shots=12500se utilizó. - El menor número de qubits en los casos de MIS (74 y 124 frente a 128 y 186 variables) se debe a la fijación de variables en el preprocesamiento.
- Las instancias de problemas para MIS proceden de la Biblioteca de Referencia de Optimización Cuántica. - La instancia para el problema del corte «Max- -Cut» es el grafo del Club de Kárate Zachary, que tiene un número cromático de 5.
Cómo empezar
Esta guía explica el funcionamiento básico del «Constrained Quantum Optimizer», mostrando cómo cargar la función y resolver problemas sencillos. Si deseas un tutorial más detallado, consulta «Cómo hallar el conjunto independiente máximo con el optimizador cuántico con restricciones de Aqarios ».
Inicia sesión con tu clave API de IBM Quantum y tu instancia CRN; a continuación, carga la función desde el catálogo.
El siguiente código da por hecho que ya has guardado tus credenciales. Para configurarlas, sigue las instrucciones que figuran en «Guarda las credenciales de tu cuenta de IBM Cloud ».
from qiskit_ibm_catalog import QiskitFunctionsCatalog
catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# Verify that you have access to the function
catalog.list()Output:
[QiskitFunction(aqarios/constrained-quantum-optimizer)]
# Load the function
optimizer = catalog.load("aqarios/constrained-quantum-optimizer")# Check the list of backends you have access to
catalog.backends()Output:
[<IBMBackend('ibm_pittsburgh')>,
<IBMBackend('ibm_boston')>,
<IBMBackend('ibm_phoenix')>,
<IBMBackend('ibm_fez')>,
<IBMBackend('ibm_miami')>,
<IBMBackend('ibm_marrakesh')>,
<IBMBackend('ibm_kingston')>]
# Select the backend you want to use
backend = catalog.backend("ibm_phoenix")Ejemplo 1: Un problema sencillo con restricciones
El primer ejemplo muestra cómo utilizar la función con archivos LP, un formato habitual para especificar problemas de optimización en la investigación operativa. Deberás formular el siguiente problema de optimización arbitrario de cinco variables binarias , sujeto a dos restricciones:
1. Plantear el problema
Expresa directamente la expresión matemática en el siguiente formato de cadena LP:
lp_str = """\\Problem name: Example
Minimize
obj: [ 2 x_1 x_2 + 4 x_2 x_3 - 2 x_3 x_4 - 4 x_4 x_5 - 4 x_1 x_3 - 8 x_2 x_5 ] / 2
Subject To
c1: x_1 + x_2 + x_3 <= 1
c2: x_3 - x_4 + x_5 = 0
Binaries
x_1 x_2 x_3 x_4 x_5
End
"""Ten en cuenta que [...] / 2 es una notación obligatoria para los objetivos cuadráticos según la norma del PL.
2. Ejecuta el optimizador
Resuelve el problema con el optimizador.
# Set up low-resource options for the simple problem
options = {"total_shots": 2000, "num_parallel": 5, "use_session": True}
# Dispatch the job
job_1 = optimizer.run(
model=lp_str, backend_name=backend.name, options=options
)
print(f"Job ID: {job_1.job_id}")Output:
Job ID: 2e06a3a8-7c29-4c76-94d7-194293363f4a
# Monitor the job status
job_1.status()Output:
'RUNNING: WAITING_FOR_QPU'
3. Obtener el resultado
La solución, que consiste en asignar los nombres de las variables a las asignaciones correspondientes, se obtiene del resultado.
result = job_1.result()
resultOutput:
{'solutions': [{'x_1': 0, 'x_2': 1, 'x_3': 0, 'x_4': 1, 'x_5': 1}],
'raw_energy': -6.0,
'obj_value': -6.0,
'feasible': True,
'metadata': {'resource_usage': {'RUNNING: MAPPING': {'CPU': 5.405},
'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU': 9.902},
'RUNNING: WAITING_FOR_QPU': {'CPU': 25.456},
'RUNNING: EXECUTING_QPU': {'CPU': 25.202},
'RUNNING: POST_PROCESSING': {'CPU': 6.481}},
'circuit_metrics': {'depth': 100.95,
'2Q-depth': 33.0,
'sx': 122.25,
'rz': 78.85,
'cz': 48.0,
'x': 0.4}}}
El solutions campo del diccionario de retorno contiene todas las mejores soluciones degeneradas encontradas. Junto con los datos de la solución, metadata se proporcionan el obj_value, un indicador feasible y adicionales.
Ejemplo 2: Conjunto independiente máximo
El problema del conjunto independiente máximo (MIS) consiste en hallar el mayor subconjunto de vértices de un grafo tal que ningún par de vértices del subconjunto comparta un arco. Este ejemplo resuelve el problema MIS en un grafo regular de 12 nodos. Para obtener más información sobre el problema y ver un ejemplo más extenso, consulta el tutorial.
El problema se ha creado con qiskit-addon-opt-mapper. Instala los paquetes necesarios si es preciso:
# %pip install networkx qiskit-addon-opt-mapperPaso 1: Definir el problema
Crea un grafo aleatorio de 3-regular y formula el problema de optimización del MIS. Cada nodo del grafo se convierte en una variable binaria, y cada arista introduce una restricción que garantiza que se seleccione, como máximo, un extremo.
import networkx as nx
from qiskit_addon_opt_mapper.applications import IndependentSet
from qiskit_addon_opt_mapper.translators import to_docplex_mp
# 12-node random 3-regular graph
G = nx.random_regular_graph(3, 12, seed=7)
# Build MIS problem and export as LP string
mis = IndependentSet(G)
mis_problem = mis.to_optimization_problem()
lp_str = to_docplex_mp(mis_problem).export_as_lp_string()
print(lp_str)Output:
\ This file has been generated by DOcplex
\ ENCODING=ISO-8859-1
\Problem name: Independent set
Maximize
obj: x_0 + x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9 + x_10 + x_11
Subject To
c0: x_0 + x_4 <= 1
c1: x_0 + x_9 <= 1
c2: x_0 + x_8 <= 1
c3: x_1 + x_2 <= 1
c4: x_1 + x_7 <= 1
c5: x_1 + x_3 <= 1
c6: x_2 + x_4 <= 1
c7: x_2 + x_11 <= 1
c8: x_3 + x_10 <= 1
c9: x_3 + x_11 <= 1
c10: x_4 + x_5 <= 1
c11: x_5 + x_10 <= 1
c12: x_5 + x_6 <= 1
c13: x_6 + x_8 <= 1
c14: x_6 + x_7 <= 1
c15: x_7 + x_9 <= 1
c16: x_8 + x_11 <= 1
c17: x_9 + x_10 <= 1
Bounds
0 <= x_0 <= 1
0 <= x_1 <= 1
0 <= x_2 <= 1
0 <= x_3 <= 1
0 <= x_4 <= 1
0 <= x_5 <= 1
0 <= x_6 <= 1
0 <= x_7 <= 1
0 <= x_8 <= 1
0 <= x_9 <= 1
0 <= x_10 <= 1
0 <= x_11 <= 1
Binaries
x_0 x_1 x_2 x_3 x_4 x_5 x_6 x_7 x_8 x_9 x_10 x_11
End
Paso 2: Ejecuta el optimizador
Resuelve el problema con el optimizador.
options = {"total_shots": 2000, "use_session": True}
# Dispatch the job
job_2 = optimizer.run(
model=lp_str, backend_name=backend.name, options=options
)
print(f"Job ID: {job_2.job_id}")Output:
Job ID: f041431c-b42e-4627-afe5-522fea61faf6
# Monitor the job status
job_2.status()Output:
'QUEUED'
Paso 3: Obtener e interpretar los resultados
Por último, recuperamos la solución y comprobamos que sea correcta.
result = job_2.result()
print(f"Feasible: {result['feasible']}")
print(f"Independent set size: {int(result['obj_value'])}")
# Extract the selected nodes
solution = result["solutions"][0]
independent_set = [
int(k.split("_")[1]) for k, v in solution.items() if v == 1
]
print(f"Selected nodes: {sorted(independent_set)}")
# Verify no two selected nodes share an edge
conflicts = [
(u, v)
for u, v in G.edges()
if u in independent_set and v in independent_set
]
print(f"Edge conflicts: {conflicts}")Output:
Feasible: True
Independent set size: 5
Selected nodes: [1, 4, 6, 9, 11]
Edge conflicts: []
Ejemplo 3: Coloreado de grafos de 3 colores ( Max-3-Cut )
El problema «Max- -Cut» divide los vértices de un grafo en grupos « » con el fin de maximizar el número de aristas cuyos extremos pertenecen a grupos diferentes. Para , esto equivale a encontrar una coloración de 3 colores que maximice el número de aristas de colores cruzados.
Formalmente, se asigna cada nodo a uno de los grupos con variables binarias para el color . La restricción «one-hot» para cada nodo garantiza una asignación única. El objetivo maximiza los enlaces entre grupos:
Las restricciones «one-hot» son ideales para los mezcladores XY, que el optimizador gestiona de forma nativa.
En este ejemplo se utiliza el grafo del Zachary Karate Club (34 nodos, 78 aristas) y se construye el modelo con Luna Model. Instala los paquetes necesarios si es preciso:
# %pip install networkx matplotlib luna-modelPaso 1: Definir el problema
En primer lugar, genera las variables binarias con el paquete luna-model . A continuación, define el objetivo e incorpora las restricciones al modelo.
import networkx as nx
from luna_model import Model, quicksum
k = 3
G = nx.karate_club_graph()
# Instantiate the Model object
model = Model(name="Max-3-Cut")
# Add binary variables
x = model.add_variables("x", shape=(G.number_of_nodes(), k))
# Add the objective by using the numpy dot abstraction
model.objective = quicksum(x[i].dot(x[j]) for i, j in G.edges)
# Bulk-add the one-hot constraints
model.add_constraints(x.sum(axis=1) == 1)
# Encode the model to send via API
model_enc = model.encode_b64()Paso 2: Ejecuta el optimizador
Resuelve el problema con el optimizador.
options = {"use_session": True}
# Dispatch the job
job_3 = optimizer.run(
model=model_enc, backend_name=backend.name, options=options
)
print(f"Job ID: {job_3.job_id}")Output:
Job ID: df911d83-9df7-44a1-bfad-5d66e08676c3
# Monitor the job status
job_3.status()Output:
'RUNNING: WAITING_FOR_QPU'
Paso 3: Obtener y visualizar los resultados
Recupera y visualiza los resultados.
result = job_3.result()
solution = result["solutions"][0]
# Map each node to its assigned color group
node_group = {}
for i in G.nodes:
for c in range(k):
if solution[f"x{i},{c}"] == 1:
node_group[i] = c
print(f"Feasible: {result['feasible']}")
print(f"Violations: {int(result['obj_value'])}")
# Visualize the partition
colors = ["tab:blue", "tab:orange", "tab:green"]
node_colors = [colors[node_group[i]] for i in G.nodes()]
nx.draw(G, nx.kamada_kawai_layout(G), node_color=node_colors, node_size=200)Output:
Feasible: True
Violations: 4
Obtener soporte
Si tienes alguna pregunta o problema, ponte en contacto con [email protected] indicando tu número de referencia.
Próximos pasos
- Solicita acceso al «Constrained Quantum Optimizer» de Aqarios.
- Consulta la referencia de la API para obtener la documentación completa sobre los parámetros y los resultados.
- Prueba el tutorial «Encontrar el conjunto independiente máximo con el optimizador cuántico con restricciones de Aqarios» para profundizar en una instancia real del banco de pruebas QOBLIB.
- Consulta la publicación «Optimización cuántica con restricciones mediante mezcladores XY iterativos con arranque en caliente ».
Referencias
- Bucher et al. (2026), «Optimización cuántica con restricciones mediante mezcladores XY iterativos con inicio en caliente » 10.1088/1367-2630/ae8ea2