Skip to main content
IBM Quantum Platform

Iskay Quantum Optimizer - una función Qiskit de Kipu Quantum

Consulte la referencia de la API

Nota
  • Las funciones Qiskit 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 IBM Quantum Platform API). Se trata de versiones preliminares sujetas a cambios.

Visión general

Con el optimizador cuántico Iskay de Kipu Quantum, podrá abordar complejos problemas de optimización utilizando los ordenadores cuánticos de IBM®. Este solucionador aprovecha el algoritmo bf-DCQO de vanguardia de Kipu, que requiere solo la función objetivo como entrada para entregar automáticamente soluciones al problema. Puede tratar problemas de optimización que impliquen hasta 156 qubits, lo que permite utilizar todos los qubits de los dispositivos cuánticos de IBM. El Optimizador utiliza un mapeo 1-to-1 entre variables clásicas y qubits, lo que permite abordar problemas de optimización con hasta 156 variables binarias.

El optimizador permite resolver problemas de optimización binarios sin restricciones. Además de la formulación QUBO (Quadratic Unconstrained Binary Optimization) de uso común, también admite problemas de optimización de orden superior (HUBO). El solucionador utiliza un algoritmo cuántico no variacional que realiza la mayor parte del cálculo en dispositivos cuánticos.

A continuación se ofrecen más detalles sobre el algoritmo utilizado y una breve guía sobre cómo utilizar la función, así como resultados de pruebas comparativas en varias instancias de problemas de distintos tamaños y complejidades.


Descripción

El Optimizador es una implementación lista para usar de los algoritmos de optimización cuántica más avanzados. Resuelve problemas de optimización ejecutando circuitos cuánticos altamente comprimidos en hardware cuántico. Esta compresión se consigue introduciendo términos contradiabáticos en la evolución temporal subyacente del sistema cuántico. El algoritmo ejecuta varias iteraciones de carreras de hardware para obtener las soluciones finales y lo combina con el postprocesamiento. Estos pasos se integran perfectamente en el flujo de trabajo del optimizador y se ejecutan automáticamente.

¿Cómo funciona el optimizador cuántico?

En esta sección se describen los fundamentos del algoritmo bf-DCQO implementado. También se puede encontrar una introducción al algoritmo en el canal Qiskit YouTube.

El algoritmo se basa en la evolución temporal de un sistema cuántico que se transforma con el tiempo, donde la solución del problema se codifica en el estado fundamental del sistema cuántico al final de la evolución. Según el teorema adiabático, esta evolución tiene que ser lenta para garantizar que el sistema permanezca en su estado fundamental. La digitalización de esta evolución es la base de la computación adiabática cuántica digitalizada (DQA) y del infame algoritmo QAOA. Sin embargo, la evolución lenta requerida no es factible para problemas de tamaño creciente, ya que da lugar a una profundidad de circuito cada vez mayor. Mediante el uso de protocolos contradiabáticos, se pueden suprimir las excitaciones no deseadas que se producen durante tiempos de evolución cortos mientras se permanece en el estado de masa. Aquí, la digitalización de este menor tiempo de evolución da lugar a circuitos cuánticos con menor profundidad y menos puertas de enredo.

Los circuitos de los algoritmos bf-DCQO suelen utilizar hasta diez veces menos puertas de enredo que DQA, y de tres a cuatro veces menos puertas de enredo que las implementaciones estándar de QAOA. Debido al menor número de puertas, se producen menos errores durante la ejecución del circuito en el hardware. Por lo tanto, el optimizador no necesita utilizar técnicas como la supresión o mitigación de errores. Su aplicación en futuras versiones puede mejorar aún más la calidad de la solución.

Aunque el algoritmo bf-DCQO utiliza iteraciones, no es variacional. Después de cada iteración del algoritmo, se mide la distribución de los estados. La distribución obtenida se utiliza para calcular el denominado campo de polarización. El campo de polarización permite iniciar la siguiente iteración a partir de un estado energético cercano a la solución encontrada anteriormente. De este modo, el algoritmo se desplaza en cada iteración hacia soluciones de menor energía. Normalmente, bastan unas diez iteraciones para converger a una solución, lo que en total requiere un número de iteraciones muy inferior al de los algoritmos variacionales, que es del orden de unas 100 iteraciones.

El optimizador combina el algoritmo bf-DCQO con el postprocesamiento clásico. Tras medir la distribución de los estados, se realiza una búsqueda local. Durante la búsqueda local, los bits de la solución medida se invierten aleatoriamente. Tras la inversión, se evalúa la energía de la nueva cadena de bits. Si la energía es menor, la cadena de bits se mantiene como la nueva solución. La búsqueda local sólo escala linealmente con el número de qubits, por lo que es computacionalmente barata. Dado que el postprocesado corrige las desviaciones de bits locales, compensa los errores de desviación de bits que suelen ser el resultado de imperfecciones del hardware y errores de lectura.

Flujo de trabajo

A continuación se presenta un esquema del flujo de trabajo del Optimizador Cuántico.

Flujo de trabajo
Flujo de trabajo del optimizador cuántico

Utilizando el optimizador cuántico, la resolución de un problema de optimización en hardware cuántico puede reducirse a

  • Formular la función objetivo del problema
  • Acceso al optimizador a través de las funciones de Qiskit
  • Ejecute el Optimizador y recoja el resultado

Referencias comparativas

Las métricas de referencia que se muestran a continuación demuestran que el optimizador aborda con eficacia problemas de hasta 156 qubits y ofrecen una visión general de la precisión y escalabilidad del optimizador en distintos tipos de problemas. Tenga en cuenta que las métricas de rendimiento reales pueden variar en función de las características específicas del problema, como el número de variables, la densidad y la localidad de los términos en la función objetivo y el orden polinómico.

La siguiente tabla incluye el ratio de aproximación (AR), una métrica definida del siguiente modo:

AR=CCmaxCminCmax,AR = \frac{C^{*} - C_\textrm{max}}{C_{\textrm{min}} - C_{\textrm{max}}},

donde CC es la función objetivo, CminC_{\textrm{min}}, CmaxC_{\textrm{max}} son sus valores mínimo y máximo, y CC^{*} es el coste de la mejor solución encontrada, respectivamente. Por lo tanto, AR=100% significa que se ha obtenido el estado básico del problema.

Ejemplo
Número de qubits
Ratio de aproximación
Tiempo total (s)
Tiempo de ejecución (s)
Número total de disparos
Número de iteraciones
Sin ponderar MaxCut28100 %1803030k5
Sin ponderar MaxCut30100 %1803030k5
Sin ponderar MaxCut32100 %1803030k5
Sin ponderar MaxCut80100 %4806090k9
Sin ponderar MaxCut100100 %3306060k6
Sin ponderar MaxCut120100 %3706060k6
HUBO 1156100 %60073100k10
HUBO 2156100 %60073100k10
  • Las instancias MaxCut con 28, 30 y 32 qubits se ejecutaron en ibm_sherbrooke. Las instancias con 80, 100 y 120 se ejecutaron en un procesador Heron r2.
  • Las instancias de HUBO también se ejecutaron en un procesador Heron r2.

Todas las instancias de benchmark son accesibles en GitHub (ver instancias de benchmark Kipu ). Encontrará un ejemplo para ejecutar estas instancias en el Ejemplo 3: Instancias de referencia.


Cómo empezar

En esta documentación, repasaremos los pasos para utilizar el optimizador cuántico Iskay. En el proceso, mostraremos rápidamente cómo cargar la función desde el catálogo y cómo convertir su problema en una entrada válida, al tiempo que le enseñamos cómo puede experimentar con diferentes parámetros opcionales.

Para ver un ejemplo más detallado, consulte el tutorial Resolver el problema de la división del mercado con el optimizador cuántico Iskay de Kipu Quantum, en el que repasamos todo el proceso de uso del solucionador Iskay para abordar el problema de la división del mercado, que representa un reto real de asignación de recursos en el que los mercados deben dividirse en regiones de ventas equilibradas para cumplir los objetivos de demanda exactos.

Autentícate utilizando tu clave API, que encontrarás en el panel de control de IBM Quantum Platform, y selecciona la función Qiskit como se indica a continuación:

Note

El siguiente código da por hecho que has guardado tus credenciales. Si aún no lo has hecho, sigue las instrucciones de «Guardar tu cuenta de IBM Cloud » para autenticarte con tu clave API.

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(
    channel="ibm_quantum_platform",
    instance="INSTANCE_CRN",
    # For `token`, use the 44-character API_KEY you created
    # and saved from the IBM Quantum Platform Home dashboard
    token="YOUR_API_KEY",
)

# 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
optimizer = catalog.load("kipu-quantum/iskay-quantum-optimizer")

Ejemplo de configuración personalizada

A continuación te mostramos cómo puedes configurar Iskay con diferentes ajustes:

custom_options = {
    "shots": 15_000,  # Higher shot count for better statistics
    "num_iterations": 12,  # More iterations for solution refinement
    "preprocessing_level": 1,  # Light preprocessing for problem simplification
    "postprocessing_level": 2,  # Maximum postprocessing for solution quality
    "transpilation_level": 3,  # Use higher transpilation level to optimize circuit
    "seed_transpiler": 42,  # Fixed seed for reproducible results
    "job_tags": ["custom_config"],  # Custom tracking tags
}

Optimización de semillas : Tenga en cuenta que seed_transpiler está establecido en None de forma predeterminada. Esto permite el proceso de optimización automática del transpilador. Cuando None, el sistema iniciará una prueba con múltiples semillas y seleccionará la que produzca la mejor profundidad de circuito, aprovechando toda la potencia del max_trials parámetro para cada nivel de transpilación.

Rendimiento del nivel de transpilación : aumentar el número de max_trials con valores más altos para transpilation_level aumentará inevitablemente el tiempo de transpilación, pero puede que no siempre cambie el circuito final, ya que esto depende en gran medida de la estructura y la complejidad específicas del circuito. Sin embargo, para algunos circuitos/problemas, la diferencia entre 10 ensayos (nivel 1) y 50 ensayos (nivel 5) puede ser considerable, por lo que explorar estos parámetros podría ser la clave para encontrar una solución satisfactoria.


Ejemplo 1: Función de coste simple

Consideremos la función de coste en la formulación de espín:

C(x0,x1,x2,x3,x4)=1+1.5x0+2x1+1.3x2+2.5x0x3+3.5x1x4+4x0x1x2C(x_0, x_1, x_2, x_3, x_4) = 1 + 1.5x_0 + 2x_1 + 1.3x_2 + 2.5x_0x_3 + 3.5x_1x_4 + 4x_0x_1x_2

donde (x0,...,x4){1,1}5(x_0, ..., x_4) \in \{-1, 1\}^5.

La solución a esta sencilla función de costes es

(x0,x1,x2,x3,x4)=(1,1,1,1,1)(x_0, x_1, x_2, x_3, x_4) = (-1, -1, -1, 1, 1)

con valor mínimo C=6C^{*} = -6

1. Crear la función objetivo

Comenzamos creando un diccionario con los coeficientes de la función objetivo de la siguiente manera:

objective_func = {
    "()": 1,
    "(0,)": 1.5,
    "(1,)": 2,
    "(2,)": 1.3,
    "(0, 3)": 2.5,
    "(1, 4)": 3.5,
    "(0, 1, 2)": 4,
}

2. Ejecuta el Optimizador

Resolvemos el problema ejecutando el optimizador. Dado que (x0,...,x4){1,1}5(x_0, ..., x_4) \in \{-1, 1\}^5 debemos fijar problem_type=spin.

# Setup options to run the optimizer
options = {"shots": 5000, "num_iterations": 5, "use_session": True}

arguments = {
    "problem": objective_func,
    "problem_type": "spin",
    "backend_name": backend_name,  # such as "ibm_fez"
    "options": options,
}

job = optimizer.run(**arguments)

# Print the ID so you can use it later, if necessary
print(job.job_id)

3. Recuperar el resultado

La solución del problema de optimización se proporciona directamente desde el optimizador.

print(job.result())

Esto mostrará un diccionario de la forma:

{'solution': {'0': -1, '1': -1, '2': -1, '3': 1, '4': 1},
 'solution_info': {'bitstring': '11100',
  'cost': -13.8,
  'seed_transpiler': 42,
  'mapping': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}},
 'prob_type': 'spin'}

Observe que el diccionario solution muestra el vector de resultados (x0,x1,x2,x3,x4)=(1,1,1,1,1)(x_0, x_1, x_2, x_3, x_4) = (-1, -1, -1, 1, 1).


Ejemplo 2: MaxCut

Muchos problemas de grafos, como MaxCut o Maximum independent set, son problemas difíciles NP y candidatos ideales para probar algoritmos y hardware cuánticos. Este ejemplo demuestra la resolución del problema MaxCut de un grafo 3-regular con el Optimizador Quantum.

Para ejecutar este ejemplo debe instalar el paquete networkx además de qiskit-ibm-catalog. Para instalarlo, ejecute el mandato siguiente:

# %pip install networkx numpy

1. Crear la función objetivo

Empieza generando un grafo 3-regular aleatorio. Para este gráfico, definimos la función objetivo del problema MaxCut.

import networkx as nx

# Create a random 3-regular graph
G = nx.random_regular_graph(3, 10, seed=42)


# Create the objective function for MaxCut in Ising formulation
def graph_to_ising_maxcut(G):
    """
    Convert a NetworkX graph to an Ising Hamiltonian for the max-cut problem.
    Args:
        G (networkx.Graph): The input graph.
    Returns:
        dict: The objective function of the Ising model
    """
    # Initialize the linear and quadratic coefficients
    objective_func = {}
    # Populate the coefficients
    for i, j in G.edges:
        objective_func[f"({i}, {j})"] = 0.5
    return objective_func


objective_func = graph_to_ising_maxcut(G)

2. Ejecuta el Optimizador

Resuelve el problema ejecutando el optimizador.

options = {"shots": 5000, "num_iterations": 5, "use_session": True}

arguments = {
    "problem": objective_func,
    "problem_type": "spin",
    "backend_name": backend_name,  # such as "ibm_fez"
    "options": options,
}

job = optimizer.run(**arguments)

3. Recuperar el resultado

Recupera el resultado y asigna la cadena de bits de la solución a los nodos del grafo original.

print(job.result())

La solución al problema Maxcut se encuentra directamente en el subdiccionario solution del objeto resultado

maxcut_solution = job.result()["solution"]

Ejemplo 3: Instancias de referencia

Las instancias de referencia están disponibles en GitHub: Instancias de referencia de Kipu.

Las instancias pueden cargarse utilizando la biblioteca pygithub . Para instalarlo, ejecute el mandato siguiente:

# %pip install pygithub

Las rutas para las instancias de referencia son:

Maxcut:

  • 'maxcut/maxcut_regular_3_100_nodes_weighted.json'
  • 'maxcut/maxcut_regular_3_140_nodes_weighted.json'
  • 'maxcut/maxcut_regular_3_150_nodes_weighted.json'
  • 'maxcut/maxcut_regular_4_130_nodes_weighted.json'

HUBO:

  • 'HUBO/hubo1_marrakesh.json'
  • 'HUBO/hubo2_marrakesh.json'

Para reproducir el rendimiento del benchmark para las instancias HUBO, seleccione el backend ibm_marrakesh y establezca direct_qubit_mapping en True en el subdiccionario options .

En el siguiente ejemplo se ejecuta la instancia de Maxcut con 150 nodos.

from github import Github
import urllib
import json
import ast

repo = "Kipu-Quantum-GmbH/benchmark-instances"
path = "maxcut/maxcut_regular_3_150_nodes_weighted.json"
gh = Github()
repo = gh.get_repo(repo)
branch = "main"
file = repo.get_contents(urllib.parse.quote(path), ref=branch)

# load json file with benchmark problem
problem_json = json.loads(file.decoded_content)

# convert objective function to compatible format
objective_func = {
    key: ast.literal_eval(value) for key, value in problem_json.items()
}


# Setup configuration to run the optimizer
options = {
    "shots": 5_000,
    "num_iterations": 5,
    "use_session": True,
    "direct_qubit_mapping": False,
}

arguments = {
    "problem": objective_func,
    "problem_type": "spin",
    "backend_name": "<BACKEND-NAME>",
    "options": options,
}

job = optimizer.run(**arguments)

result = job.result()

Casos de uso

Los casos de uso típicos del solucionador de optimización son los problemas de optimización combinatoria. Puede resolver problemas de muchos sectores, como el financiero, el farmacéutico o el logístico. He aquí algunos ejemplos.

Si está interesado en abordar un caso de uso específico y desarrollar un mapeo dedicado, podemos ayudarle. Contáctenos.


Obtener soporte

Para obtener ayuda, póngase en contacto con [email protected].


Próximos pasos


Información adicional

Iskay, como el nombre de nuestra empresa, Kipu Quantum, es una palabra peruana. Aunque somos una startup de Alemania, estas palabras proceden del país natal de uno de nuestros cofundadores, donde el Quipu fue una de las primeras máquinas de cálculo desarrolladas por la humanidad 2000 años antes de Cristo.

¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.