Aller au contenu principal

Iskay Quantum Optimizer - Une fonction Qiskit par Kipu Quantum

Voir la référence API

Note
  • Les fonctions Qiskit sont une fonctionnalité expérimentale disponible uniquement pour les utilisateurs des plans IBM Quantum® Premium, Flex et On-Prem (via l'API IBM Quantum Platform). Elles sont en version préliminaire et sont susceptibles d'évoluer.

Vue d'ensemble

Avec l'Iskay Quantum Optimizer de Kipu Quantum, tu peux aborder des problèmes d'optimisation complexes à l'aide des ordinateurs quantiques IBM®. Ce solveur s'appuie sur l'algorithme de pointe bf-DCQO de Kipu, qui ne nécessite que la fonction objectif en entrée pour livrer automatiquement les solutions aux problèmes. Il peut traiter des problèmes d'optimisation impliquant jusqu'à 156 qubits, ce qui permet d'utiliser tous les qubits des appareils quantiques IBM. L'Optimizer utilise un mappage 1-pour-1 entre les variables classiques et les qubits, ce qui te permet de traiter des problèmes d'optimisation comportant jusqu'à 156 variables binaires.

L'Optimizer permet de résoudre des problèmes d'optimisation binaire non contraints. En plus de la formulation QUBO (Quadratic Unconstrained Binary Optimization) couramment utilisée, il prend également en charge les problèmes d'optimisation d'ordre supérieur (HUBO). Le solveur utilise un algorithme quantique non variationnel, effectuant la majeure partie du calcul sur des appareils quantiques.

Ce qui suit fournit plus de détails sur l'algorithme utilisé et un guide succinct sur l'utilisation de la fonction, ainsi que des résultats de benchmark sur diverses instances de problèmes de tailles et complexités différentes.

Description

L'Optimizer est une implémentation clé en main d'algorithmes d'optimisation quantique de pointe. Il résout des problèmes d'optimisation en exécutant des circuits quantiques hautement compressés sur du matériel quantique. Cette compression est obtenue en introduisant des termes contradiabatiques dans l'évolution temporelle sous-jacente du système quantique. L'algorithme effectue plusieurs itérations d'exécutions matérielles pour obtenir les solutions finales et les combine avec un post-traitement. Ces étapes sont intégrées de manière transparente dans le flux de travail de l'Optimizer et sont exécutées automatiquement.

Comment fonctionne le Quantum Optimizer ?

Cette section présente les bases de l'algorithme bf-DCQO implémenté. Une introduction à l'algorithme est également disponible sur la chaîne YouTube de Qiskit.

L'algorithme repose sur l'évolution temporelle d'un système quantique qui se transforme au fil du temps, la solution du problème étant encodée dans l'état fondamental du système quantique à la fin de l'évolution. D'après le théorème adiabatique, cette évolution doit être lente pour garantir que le système reste dans son état fondamental. La numérisation de cette évolution est la base du calcul adiabatique quantique numérisé (DQA) et du célèbre algorithme QAOA. Cependant, l'évolution lente requise n'est pas réalisable pour des tailles de problèmes croissantes, car elle entraîne une profondeur de circuit croissante. En utilisant des protocoles contradiabatiques, on peut supprimer les excitations indésirables se produisant pendant de courtes durées d'évolution tout en restant dans l'état fondamental. Ici, la numérisation de cette durée d'évolution plus courte produit des circuits quantiques de moindre profondeur avec moins de portes enchevêtrantes.

Les circuits des algorithmes bf-DCQO utilisent généralement jusqu'à dix fois moins de portes enchevêtrantes que DQA, et trois à quatre fois moins de portes enchevêtrantes que les implémentations QAOA standard. En raison du plus faible nombre de portes, moins d'erreurs surviennent lors de l'exécution des circuits sur le matériel. Ainsi, l'optimizer n'a pas besoin de recourir à des techniques de suppression ou d'atténuation des erreurs. Leur implémentation dans les versions futures pourra améliorer encore davantage la qualité des solutions.

Bien que l'algorithme bf-DCQO utilise des itérations, il est non variationnel. Après chaque itération de l'algorithme, la distribution des états est mesurée. La distribution obtenue est utilisée pour calculer ce que l'on appelle un champ de biais. Ce champ de biais permet de démarrer l'itération suivante à partir d'un état d'énergie proche de la solution précédemment trouvée. Ainsi, l'algorithme converge à chaque itération vers des solutions d'énergie plus basse. En règle générale, une dizaine d'itérations suffisent pour converger vers une solution, nécessitant au total un nombre d'itérations bien inférieur à celui des algorithmes variationnels, qui est de l'ordre d'une centaine d'itérations.

L'optimizer combine l'algorithme bf-DCQO avec un post-traitement classique. Après avoir mesuré la distribution des états, une recherche locale est effectuée. Lors de la recherche locale, les bits de la solution mesurée sont retournés aléatoirement. Après le retournement, l'énergie du nouveau bitstring est évaluée. Si l'énergie est plus basse, le bitstring est conservé comme nouvelle solution. La recherche locale ne croît que linéairement avec le nombre de qubits ; elle est donc peu coûteuse en termes de calcul. Comme le post-traitement corrige les retournements de bits locaux, il compense les erreurs de flip de bit qui résultent souvent des imperfections matérielles et des erreurs de lecture.

Flux de travail

Voici un schéma du flux de travail du Quantum Optimizer.

Workflow

En utilisant le Quantum Optimizer, la résolution d'un problème d'optimisation sur du matériel quantique peut être réduite à :

  • Formuler la fonction objectif du problème
  • Accéder à l'Optimizer via les fonctions Qiskit
  • Exécuter l'Optimizer et collecter le résultat

Benchmarks

Les métriques de benchmark ci-dessous montrent que l'Optimizer traite efficacement des problèmes impliquant jusqu'à 156 qubits et offrent un aperçu général de la précision et de la scalabilité de l'optimizer sur différents types de problèmes. Note que les métriques de performance réelles peuvent varier en fonction des caractéristiques spécifiques du problème, telles que le nombre de variables, la densité et la localité des termes dans la fonction objectif, et l'ordre polynomial.

Le tableau suivant inclut le ratio d'approximation (AR), une métrique définie comme suit :

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

CC est la fonction objectif, CminC_{\textrm{min}}, CmaxC_{\textrm{max}} sont ses valeurs minimale et maximale, et CC^{*} est le coût de la meilleure solution trouvée, respectivement. Ainsi, AR=100% signifie que l'état fondamental du problème a été obtenu.

ExempleNombre de qubitsRatio d'approximationTemps total (s)Utilisation runtime (s)Nombre total de shotsNombre d'itérations
MaxCut non pondéré28100%1803030k5
MaxCut non pondéré30100%1803030k5
MaxCut non pondéré32100%1803030k5
MaxCut non pondéré80100%4806090k9
MaxCut non pondéré100100%3306060k6
MaxCut non pondéré120100%3706060k6
HUBO 1156100%60070100k10
HUBO 2156100%60070100k10
  • Les instances MaxCut avec 28, 30 et 32 qubits ont été exécutées sur ibm_sherbrooke. Les instances avec 80, 100 et 120 ont été exécutées sur un processeur Heron r2.
  • Les instances HUBO ont également été exécutées sur un processeur Heron r2.

Toutes les instances de benchmark sont accessibles sur GitHub (voir Kipu benchmark instances). Un exemple pour exécuter ces instances se trouve dans Exemple 3 : Instances de benchmark.

Premiers pas

Dans cette documentation, nous allons parcourir les étapes d'utilisation de l'Iskay Quantum Optimizer. Au cours du processus, nous montrerons rapidement comment charger la fonction depuis le catalogue et comment convertir ton problème en une entrée valide, tout en montrant comment tu peux expérimenter différents paramètres optionnels.

Pour un exemple plus détaillé, consulte le tutoriel Résoudre le problème de Market Split avec l'Iskay Quantum Optimizer de Kipu Quantum, où nous parcourons l'ensemble du processus d'utilisation d'Iskay Solver pour aborder le problème de Market Split, qui représente un défi d'allocation de ressources réel où les marchés doivent être partitionnés en régions de vente équilibrées pour répondre à des objectifs de demande précis.

Authentifie-toi en utilisant ta clé API, disponible sur le tableau de bord IBM Quantum Platform, et sélectionne la fonction Qiskit comme suit :

# Added by doQumentation — required packages for this notebook
!pip install -q PyGithub networkx qiskit-ibm-catalog
# ruff: noqa: F821
remarque

Le code suivant suppose que tu as sauvegardé tes identifiants. Si ce n'est pas le cas, suis les instructions dans sauvegarder ton compte IBM Cloud pour t'authentifier avec ta clé API.

from qiskit_ibm_catalog import QiskitFunctionsCatalog

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

# Access Function
optimizer = catalog.load("kipu-quantum/iskay-quantum-optimizer")

Exemple de configuration personnalisée

Voici comment tu pourrais configurer Iskay avec différents paramètres :

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, # Using higher transpilation level for circuit optimization
"seed_transpiler": 42, # Fixed seed for reproducible results
"job_tags": ["custom_config"], # Custom tracking tags
}

Optimisation du seed : Note que seed_transpiler est défini à None par défaut. Cela permet le processus d'optimisation automatique du transpiler. Quand il vaut None, le système lance un essai avec plusieurs seeds et sélectionne celui qui produit la meilleure profondeur de circuit, tirant parti de la puissance totale du paramètre max_trials pour chaque niveau de transpilation.

Performance des niveaux de transpilation : Augmenter le nombre de max_trials avec des valeurs plus élevées pour transpilation_level augmentera inévitablement le temps de transpilation, mais cela ne modifiera pas toujours le circuit final — cela dépend fortement de la structure et de la complexité spécifiques du circuit. Pour certains circuits/problèmes, cependant, la différence entre 10 essais (niveau 1) et 50 essais (niveau 5) peut être dramatique, donc explorer ces paramètres pourrait être la clé pour trouver avec succès une solution.

Exemple 1 : Fonction de coût simple

Considère la fonction de coût dans la formulation spin :

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

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

La solution de cette fonction de coût simple est

(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)

avec la valeur minimale C=6C^{*} = -6

1. Créer la fonction objectif

On commence par créer un dictionnaire avec les coefficients de la fonction objectif comme suit :

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

2. Exécuter l'Optimizer

On résout le problème en exécutant l'optimizer. Puisque (x0,...,x4){1,1}5(x_0, ..., x_4) \in \{-1, 1\}^5, on doit définir 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)

3. Récupérer le résultat

La solution du problème d'optimisation est fournie directement par l'optimizer.

print(job.result())

Cela affichera un dictionnaire de la forme :

{'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'}

Remarque que le dictionnaire solution affiche le vecteur résultat (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).

Exemple 2 : MaxCut

De nombreux problèmes de graphes comme MaxCut ou l'ensemble indépendant maximum sont des problèmes NP-difficiles et des candidats idéaux pour tester les algorithmes quantiques et le matériel. Cet exemple montre comment résoudre le problème MaxCut d'un graphe 3-régulier avec le Quantum Optimizer.

Pour exécuter cet exemple, tu dois installer le paquet networkx en plus de qiskit-ibm-catalog. Pour l'installer, exécute la commande suivante :

# %pip install networkx numpy

1. Créer la fonction objectif

Commence par générer un graphe 3-régulier aléatoire. Pour ce graphe, on définit la fonction objectif du problème 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. Exécuter l'Optimizer

Résous le problème en exécutant l'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)

3. Récupérer le résultat

Récupère le résultat et mappe le bitstring de solution en retour vers les nœuds du graphe d'origine.

print(job.result())

La solution du problème Maxcut est directement contenue dans le sous-dictionnaire solution de l'objet résultat

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

Exemple 3 : Instances de benchmark

Les instances de benchmark sont disponibles sur GitHub : Kipu benchmark instances.

Les instances peuvent être chargées à l'aide de la bibliothèque pygithub. Pour l'installer, exécute la commande suivante :

# %pip install pygithub

Les chemins des instances de benchmark sont :

Maxcut :

  • 'maxcut/maxcut_28_nodes.json'
  • 'maxcut/maxcut_30_nodes.json'
  • 'maxcut/maxcut_32_nodes.json'
  • 'maxcut/maxcut_80_nodes.json'
  • 'maxcut/maxcut_100_nodes.json'
  • 'maxcut/maxcut_120_nodes.json'

HUBO :

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

Pour reproduire la performance du benchmark pour les instances HUBO, sélectionne le backend ibm_marrakesh et définis direct_qubit_mapping à True dans le sous-dictionnaire options. L'exemple suivant exécute l'instance Maxcut avec 32 nœuds.

from github import Github
import urllib
import json
import ast

repo = "Kipu-Quantum-GmbH/benchmark-instances"
path = "maxcut/maxcut_32_nodes.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": "ibm_brisbane",
"options": options,
}

job = optimizer.run(**arguments)

result = job.result()

Cas d'utilisation

Les cas d'utilisation typiques du solveur d'optimisation sont les problèmes d'optimisation combinatoire. Tu peux résoudre des problèmes issus de nombreux secteurs comme la finance, la pharmacie ou la logistique. Quelques exemples suivent.

Si tu es intéressé par l'étude d'un cas d'utilisation spécifique et le développement d'un mappage dédié, nous pouvons t'aider. Contacte-nous.

Obtenir de l'aide

Pour du soutien, contacte support@kipu-quantum.com.

Prochaines étapes

Informations supplémentaires

Iskay, tout comme le nom de notre entreprise Kipu Quantum, est un mot péruvien. Bien que nous soyons une startup allemande, ces mots viennent du pays natal de l'un de nos co-fondateurs, où le Quipu fut l'une des toutes premières machines à calculer développées par l'humanité, il y a 2000 ans avant J.-C.