Skip to main content
IBM Quantum Platform

Iskay Quantum Optimizer - Une fonction Qiskit par Kipu Quantum

Consultez la documentation de l'API

Remarque
  • Les fonctions Qiskit sont une fonctionnalité expérimentale disponible uniquement pour IBM Quantum® Premium Plan, Flex Plan, et On-Prem (via IBM Quantum Platform API). Elles sont en cours de publication et peuvent être modifiées.

Aperçu

Avec l'optimiseur quantique Iskay de Kipu Quantum, vous pouvez vous attaquer à des problèmes d'optimisation complexes en utilisant les ordinateurs quantiques IBM®. Ce solveur exploite l'algorithme de pointe bf-DCQO de Kipu, nécessitant uniquement la fonction objective comme entrée pour fournir automatiquement des 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 dispositifs quantiques IBM. L'Optimizer utilise une correspondance 1-to-1 entre les variables classiques et les qubits, ce qui vous permet d'aborder les problèmes d'optimisation avec jusqu'à 156 variables binaires.

L'Optimizer permet de résoudre des problèmes d'optimisation binaire sans contrainte. Outre 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 plupart des calculs sur des dispositifs quantiques.

Les paragraphes suivants fournissent plus de détails sur l'algorithme utilisé et un bref guide sur l'utilisation de la fonction, ainsi que des résultats d'analyse comparative sur diverses instances de problèmes de tailles et de complexités différentes.


Description

L'Optimizer est une implémentation prête à l'emploi d'algorithmes d'optimisation quantique de pointe. Il résout les 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 contrediabatiques dans l'évolution temporelle sous-jacente du système quantique. L'algorithme exécute plusieurs itérations du matériel pour obtenir les solutions finales et les combine avec le 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 l'optimiseur quantique?

Cette section présente les principes fondamentaux de l'algorithme bf-DCQO mis en œuvre. Une introduction à l'algorithme est également disponible sur la chaîne YouTube Qiskit YouTube.

L'algorithme est basé sur l'évolution temporelle d'un système quantique qui est transformé au fil du temps, où la solution du problème est encodée dans l'état fondamental du système quantique à la fin de l'évolution. Selon le théorème adiabatique, cette évolution doit être lente pour que le système reste dans son état fondamental. La numérisation de cette évolution est à la base du calcul quantique adiabatique numérisé (CQA) et du tristement célèbre algorithme QAOA. Cependant, l'évolution lente requise n'est pas réalisable pour des problèmes de taille croissante, car elle entraîne une augmentation de la profondeur du circuit. En utilisant des protocoles contrediabatiques, vous pouvez supprimer les excitations indésirables survenant pendant des temps d'évolution courts tout en restant dans l'état fondamental. Ici, la numérisation de ce temps d'évolution plus court permet d'obtenir des circuits quantiques avec une profondeur plus courte et moins de portes d'enchevêtrement.

Les circuits des algorithmes bf-DCQO utilisent généralement jusqu'à dix fois moins de portes d'enchevêtrement que l'AQD, et trois à quatre fois moins de portes d'enchevêtrement que les implémentations standard de l'AQAO. En raison du nombre réduit de portes, moins d'erreurs se produisent lors de l'exécution du circuit sur le matériel. L'optimiseur n'a donc pas besoin d'utiliser des techniques telles que la suppression ou l'atténuation des erreurs. Leur mise en œuvre dans les versions futures peut encore améliorer la qualité de la solution.

Bien que l'algorithme bf-DCQO utilise des itérations, il n'est pas 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 le champ de polarisation. Le champ de biais permet de démarrer l'itération suivante à partir d'un état d'énergie proche de la solution trouvée précédemment. De cette manière, l'algorithme se déplace à chaque itération vers des solutions de moindre énergie. Typiquement, une dizaine d'itérations suffisent pour converger vers une solution, ce qui nécessite 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'optimiseur combine l'algorithme bf-DCQO avec un post-traitement classique. Après avoir mesuré la distribution des états, une recherche locale est effectuée. Pendant la recherche locale, les bits de la solution mesurée sont inversés de manière aléatoire. Après le retournement, l'énergie de la nouvelle chaîne de bits est évaluée. Si l'énergie est inférieure, la chaîne de bits est conservée comme nouvelle solution. La recherche locale n'évolue que linéairement avec le nombre de qubits; elle est donc peu coûteuse sur le plan informatique. Étant donné que le post-traitement corrige les inversions locales de bits, il compense les erreurs d'inversions de bits qui résultent souvent d'imperfections matérielles et d'erreurs de lecture.

Flux de travaux

Voici un schéma du déroulement des opérations de l'Optimiseur quantique.

Flux de travail
Flux de travail de l'optimiseur quantique

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

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

Tests de performances

Les mesures de référence ci-dessous montrent que l'optimiseur traite efficacement des problèmes impliquant jusqu'à 156 qubits et offrent un aperçu général de la précision et de l'évolutivité de l'optimiseur pour différents types de problèmes. Notez que les mesures 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 de la fonction objective, et l'ordre polynomial.

Le tableau suivant inclut le ratio d'approximation (RA), une mesure définie comme suit :

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

CC est la fonction objective, 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. Par conséquent, AR=100% signifie que l'état fondamental du problème a été obtenu.

Exemple
Nombre de qubits
Rapport d'approximation
Durée totale (s)
Utilisation du temps d'exécution (s)
Nombre total de tirs
Nombre d'itérations
Non pondéré MaxCut28100 %1803030k5
Non pondéré MaxCut30100 %1803030k5
Non pondéré MaxCut32100 %1803030k5
Non pondéré MaxCut80100 %4806090k9
Non pondéré MaxCut100100 %3306060k6
Non pondéré MaxCut130100 %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 de 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 référence sont accessibles sur GitHub (voir instances de référence Kipu ). Un exemple d'exécution de ces instances est présenté dans l' exemple 3 : Instances de référence.


Premiers pas

Dans cette documentation, nous allons passer en revue les étapes d'utilisation de l'optimiseur quantique Iskay. Au cours de ce processus, nous vous montrerons rapidement comment charger la fonction à partir du catalogue et comment convertir votre problème en une entrée valide, tout en vous montrant comment vous pouvez tester différents paramètres optionnels.

Pour un exemple plus détaillé, veuillez consulter le tutoriel « Résoudre le problème de la segmentation du marché avec l'optimiseur Iskay Quantum de Kipu Quantum », dans lequel nous parcourons l'ensemble du processus d'utilisation du solveur Iskay pour résoudre le problème de la segmentation du marché, qui représente un défi réel en matière d'allocation des ressources, où les marchés doivent être divisés en zones de vente équilibrées afin de répondre à des objectifs de demande précis.

Authentifiez-vous à l'aide de votre clé API, que vous trouverez sur le tableau de bord de la plate-forme Quantum IBM, et sélectionnez la fonction Qiskit comme suit :

Note

Le code suivant part du principe que vous avez enregistré vos identifiants. Si ce n'est pas le cas, suivez les instructions de la section « Sauvegarder votre compte IBM Cloud » pour vous authentifier à l'aide de votre clé 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")

Exemple de configuration personnalisée

Voici comment vous pouvez 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,  # Use higher transpilation level to optimize circuit
    "seed_transpiler": 42,  # Fixed seed for reproducible results
    "job_tags": ["custom_config"],  # Custom tracking tags
}

Optimisation des graines : Notez que seed_transpiler est défini par défaut None sur. Cela permet le processus d'optimisation automatique du transcompilateur. Lorsque None, le système lancera un essai avec plusieurs graines et sélectionnera celle qui produit la meilleure profondeur de circuit, en exploitant toute la puissance du max_trials paramètre pour chaque niveau de transpilation.

Performances au niveau de la 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 nécessairement le circuit final. Cela dépend en grande partie 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 considérable, de sorte que l'exploration de ces paramètres pourrait être la clé pour trouver une solution.


Exemple 1 : Fonction de coût simple

Considérons la fonction de coût dans la formulation de 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 à cette fonction de coût simple est la suivante

(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 une valeur minimale C=6C^{*} = -6

1. Créer la fonction objectif

Nous commençons par créer un dictionnaire avec les coefficients de la fonction objective 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écutez l'optimiseur

Nous résolvons le problème en exécutant l'optimiseur. Puisque (x0,...,x4){1,1}5(x_0, ..., x_4) \in \{-1, 1\}^5 nous devons mettre 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. Récupérer le résultat

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

print(job.result())

Un dictionnaire de la forme s'affiche :

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

Remarquez que le dictionnaire solution affiche le vecteur de 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 tels que MaxCut ou Maximum independent set sont des problèmes NP-hard et des candidats idéaux pour tester les algorithmes et le matériel quantiques. Cet exemple illustre la résolution du problème MaxCut d'un graphe 3-régulier à l'aide de Quantum Optimizer.

Pour exécuter cet exemple, vous devez installer le paquet networkx en plus du paquet qiskit-ibm-catalog. Pour l'installer, exécutez la commande suivante :

# %pip install networkx numpy

1. Créer la fonction objectif

Commencez par générer un graphe 3-régulier aléatoire. Pour ce graphique, nous définissons la fonction objective 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écutez l'optimiseur

Résoudre le problème en exécutant l'optimiseur.

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érer le résultat et faire correspondre la chaîne de bits de la solution aux nœuds du graphe d'origine.

print(job.result())

La solution au 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 référence

Les instances de référence sont disponibles sur GitHub: Instances de référence Kipu.

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

# %pip install pygithub

Les chemins pour les instances de référence sont les suivants :

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'

Pour reproduire les performances du benchmark pour les instances HUBO, sélectionnez le backend ibm_marrakesh et définissez direct_qubit_mapping comme True dans le sous-dictionnaire options .

L'exemple suivant exécute l'instance Maxcut avec 150 nœuds.

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

Cas d'utilisation

Les cas d'utilisation typiques du solveur d'optimisation sont les problèmes d'optimisation combinatoire. Vous pouvez résoudre des problèmes dans de nombreux secteurs tels que la finance, la pharmacie ou la logistique. En voici quelques exemples.

Si vous souhaitez aborder un cas d'utilisation spécifique et développer un mappage dédié, nous pouvons vous aider. Contactez-nous.


Obtenir de l'aide

Pour obtenir de l'aide, contactez [email protected].


Etapes suivantes


Renseignements supplémentaires

Iskay, 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 cofondateurs, où le Quipu était l'une des toutes premières machines à calculer développées par l'humanité 2000 ans avant notre ère.

Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.