Vai al contenuto principale

Iskay Quantum Optimizer - Una Qiskit Function di Kipu Quantum

Consulta il riferimento API

Nota
  • Le Qiskit Functions sono una funzionalità sperimentale disponibile solo per gli utenti dei piani IBM Quantum® Premium Plan, Flex Plan e On-Prem (tramite IBM Quantum Platform API). Sono in stato di anteprima e soggette a modifiche.

Panoramica​

Con l'Iskay Quantum Optimizer di Kipu Quantum puoi affrontare problemi di ottimizzazione complessi usando i computer quantistici IBM®. Questo solver sfrutta il all'avanguardia algoritmo bf-DCQO di Kipu, richiedendo solo la funzione obiettivo come input per fornire automaticamente le soluzioni al problema. È in grado di gestire problemi di ottimizzazione con fino a 156 qubit, consentendo l'utilizzo di tutti i qubit dei dispositivi quantistici IBM. L'Optimizer usa una mappatura 1-a-1 tra variabili classiche e qubit, il che ti permette di affrontare problemi di ottimizzazione con fino a 156 variabili binarie.

L'Optimizer consente di risolvere problemi di ottimizzazione binaria non vincolata. Oltre alla formulazione QUBO (Quadratic Unconstrained Binary Optimization) comunemente usata, supporta anche problemi di ottimizzazione di ordine superiore (HUBO). Il solver utilizza un algoritmo quantistico non variazionale, eseguendo la maggior parte del calcolo su dispositivi quantistici.

Di seguito sono forniti maggiori dettagli sull'algoritmo utilizzato, una breve guida su come usare la funzione e risultati di benchmarking su varie istanze di problemi di dimensioni e complessità diverse.

Descrizione​

L'Optimizer è un'implementazione pronta all'uso di algoritmi di ottimizzazione quantistica all'avanguardia. Risolve i problemi di ottimizzazione eseguendo circuiti quantistici altamente compressi su hardware quantistico. Questa compressione si ottiene introducendo termini controadiabatici nell'evoluzione temporale sottostante del sistema quantistico. L'algoritmo esegue diverse iterazioni di esecuzioni hardware per ottenere le soluzioni finali e le combina con un post-processing. Questi passaggi sono integrati senza soluzione di continuità nel flusso di lavoro dell'Optimizer e vengono eseguiti automaticamente.

Come funziona il Quantum Optimizer?​

Questa sezione illustra le basi dell'algoritmo bf-DCQO implementato. Un'introduzione all'algoritmo è disponibile anche sul canale YouTube di Qiskit.

L'algoritmo si basa sull'evoluzione temporale di un sistema quantistico che si trasforma nel tempo, dove la soluzione del problema è codificata nello stato fondamentale del sistema quantistico al termine dell'evoluzione. Secondo il teorema adiabatico, questa evoluzione deve essere lenta per garantire che il sistema rimanga nel suo stato fondamentale. Digitalizzare questa evoluzione è la base del calcolo adiabatico digitale quantistico (DQA) e del noto algoritmo QAOA. Tuttavia, la necessaria evoluzione lenta non è praticabile per problemi di dimensioni crescenti, poiché comporta un aumento della profondità del circuito. Usando protocolli controadiabatici, puoi sopprimere le eccitazioni indesiderate che si verificano durante brevi tempi di evoluzione, mantenendosi comunque nello stato fondamentale. Qui, digitalizzare questo tempo di evoluzione più breve produce circuiti quantistici con profondità minore e meno gate di entanglement.

I circuiti degli algoritmi bf-DCQO utilizzano tipicamente fino a dieci volte meno gate di entanglement rispetto al DQA, e da tre a quattro volte meno gate di entanglement rispetto alle implementazioni standard di QAOA. Grazie al minor numero di gate, si verificano meno errori durante l'esecuzione del circuito sull'hardware. Di conseguenza, l'optimizer non richiede l'uso di tecniche come la soppressione degli errori o la mitigazione degli errori. Implementarle in versioni future potrà migliorare ulteriormente la qualità delle soluzioni.

Sebbene l'algoritmo bf-DCQO usi iterazioni, è non variazionale. Dopo ogni iterazione dell'algoritmo, viene misurata la distribuzione degli stati. La distribuzione ottenuta viene usata per calcolare un cosiddetto bias-field. Il bias-field consente di avviare l'iterazione successiva da uno stato energetico vicino alla soluzione trovata in precedenza. In questo modo, l'algoritmo si sposta a ogni iterazione verso soluzioni a energia inferiore. Tipicamente, sono sufficienti circa dieci iterazioni per convergere a una soluzione, richiedendo in totale un numero molto inferiore di iterazioni rispetto agli algoritmi variazionali, che è dell'ordine di circa 100 iterazioni.

L'optimizer combina l'algoritmo bf-DCQO con un post-processing classico. Dopo aver misurato la distribuzione degli stati, viene eseguita una ricerca locale. Durante la ricerca locale, i bit della soluzione misurata vengono invertiti casualmente. Dopo l'inversione, viene valutata l'energia della nuova stringa di bit. Se l'energia è inferiore, la stringa di bit viene mantenuta come nuova soluzione. La ricerca locale scala solo linearmente con il numero di qubit; è quindi computazionalmente poco costosa. Poiché il post-processing corregge le inversioni di bit locali, compensa gli errori di bit-flip che spesso sono il risultato di imperfezioni hardware e errori di lettura.

Flusso di lavoro​

Di seguito è riportato uno schema del flusso di lavoro del Quantum Optimizer.

Flusso di lavoro

Usando il Quantum Optimizer, la risoluzione di un problema di ottimizzazione su hardware quantistico può essere ridotta a:

  • Formulare la funzione obiettivo del problema
  • Accedere all'Optimizer tramite Qiskit Functions
  • Eseguire l'Optimizer e raccogliere il risultato

Benchmark​

Le metriche di benchmark riportate di seguito mostrano che l'Optimizer affronta efficacemente problemi che coinvolgono fino a 156 qubit e offrono una panoramica generale dell'accuratezza e della scalabilità dell'optimizer su diversi tipi di problemi. Nota che le metriche di prestazione effettive possono variare in base alle caratteristiche specifiche del problema, come il numero di variabili, la densità e la località dei termini nella funzione obiettivo e l'ordine polinomiale.

La tabella seguente include il rapporto di approssimazione (AR), una metrica definita come segue:

AR=C∗−CmaxCmin−Cmax,AR = \frac{C^{*} - C_\textrm{max}}{C_{\textrm{min}} - C_{\textrm{max}}},

dove CC è la funzione obiettivo, CminC_{\textrm{min}}, CmaxC_{\textrm{max}} sono rispettivamente i suoi valori minimo e massimo, e C∗C^{*} è il costo della migliore soluzione trovata. Pertanto, AR=100% significa che è stato ottenuto lo stato fondamentale del problema.

EsempioNumero di qubitRapporto di approssimazioneTempo totale (s)Utilizzo runtime (s)Numero totale di shotsNumero di iterazioni
Unweighted MaxCut28100%1803030k5
Unweighted MaxCut30100%1803030k5
Unweighted MaxCut32100%1803030k5
Unweighted MaxCut80100%4806090k9
Unweighted MaxCut100100%3306060k6
Unweighted MaxCut120100%3706060k6
HUBO 1156100%60070100k10
HUBO 2156100%60070100k10
  • Le istanze MaxCut con 28, 30 e 32 qubit sono state eseguite su ibm_sherbrooke. Le istanze con 80, 100 e 120 qubit sono state eseguite su un processore Heron r2.
  • Anche le istanze HUBO sono state eseguite su un processore Heron r2.

Tutte le istanze di benchmark sono accessibili su GitHub (vedi istanze di benchmark Kipu). Un esempio per eseguire queste istanze si trova in Esempio 3: Istanze di benchmark.

Per iniziare​

In questa documentazione, seguiremo i passaggi per utilizzare l'Iskay Quantum Optimizer. Nel processo, mostreremo rapidamente come caricare la funzione dal catalogo e come convertire il tuo problema in un input valido, mostrando al contempo come puoi sperimentare con diversi parametri opzionali.

Per un esempio più dettagliato, consulta il tutorial Risolvi il problema del Market Split con l'Iskay Quantum Optimizer di Kipu Quantum, dove lavoriamo attraverso l'intero processo di utilizzo dell'Iskay Solver per affrontare il problema del Market Split, che rappresenta una sfida reale di allocazione delle risorse in cui i mercati devono essere suddivisi in regioni di vendita bilanciate per soddisfare obiettivi di domanda esatti.

Autentica usando la tua chiave API, disponibile sulla dashboard di IBM Quantum Platform, e seleziona la Qiskit Function come segue:

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

Il codice seguente presuppone che tu abbia salvato le tue credenziali. Se non lo hai fatto, segui le istruzioni in salva il tuo account IBM Cloud per autenticarti con la tua chiave 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")

Esempio di configurazione personalizzata​

Ecco come potresti configurare Iskay con impostazioni diverse:

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
}

Ottimizzazione del seed: Nota che seed_transpiler è impostato su None per impostazione predefinita. Questo abilita il processo di ottimizzazione automatica del Transpiler. Quando è None, il sistema avvierà un tentativo con più seed e selezionerà quello che produce la migliore profondità del circuito, sfruttando appieno il parametro max_trials per ogni livello di transpilazione.

Prestazioni del livello di transpilazione: Aumentare il numero di max_trials con valori più alti per transpilation_level aumenterà inevitabilmente il tempo di transpilazione, ma potrebbe non modificare sempre il circuito finale — questo dipende molto dalla struttura e dalla complessità specifiche del circuito. Per alcuni circuiti/problemi, tuttavia, la differenza tra 10 tentativi (livello 1) e 50 tentativi (livello 5) può essere notevole, quindi esplorare questi parametri potrebbe essere la chiave per trovare con successo una soluzione.

Esempio 1: Funzione di costo semplice​

Considera la funzione di costo in formulazione 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

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

La soluzione di questa semplice funzione di costo è

(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 valore minimo C∗=−6C^{*} = -6

1. Crea la funzione obiettivo​

Iniziamo creando un dizionario con i coefficienti della funzione obiettivo come segue:

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

2. Esegui l'Optimizer​

Risolviamo il problema eseguendo l'optimizer. Poiché (x0,...,x4)∈{−1,1}5(x_0, ..., x_4) \in \{-1, 1\}^5, dobbiamo impostare 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. Recupera il risultato​

La soluzione del problema di ottimizzazione viene fornita direttamente dall'optimizer.

print(job.result())

Questo mostrerà un dizionario della 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'}

Nota che il dizionario solution mostra il vettore risultato (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).

Esempio 2: MaxCut​

Molti problemi su grafi come MaxCut o Maximum Independent Set sono problemi NP-hard e candidati ideali per testare algoritmi quantistici e hardware. Questo esempio dimostra la risoluzione del problema MaxCut su un grafo 3-regolare con il Quantum Optimizer.

Per eseguire questo esempio devi installare il pacchetto networkx in aggiunta a qiskit-ibm-catalog. Per installarlo, esegui il seguente comando:

# %pip install networkx numpy

1. Crea la funzione obiettivo​

Inizia generando un grafo 3-regolare casuale. Per questo grafo, definiamo la funzione obiettivo 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. Esegui l'Optimizer​

Risolvi il problema eseguendo 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. Recupera il risultato​

Recupera il risultato e mappa la stringa di bit della soluzione sui nodi del grafo originale.

print(job.result())

La soluzione al problema MaxCut è direttamente contenuta nel sotto-dizionario solution dell'oggetto risultato

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

Esempio 3: Istanze di benchmark​

Le istanze di benchmark sono disponibili su GitHub: istanze di benchmark Kipu.

Le istanze possono essere caricate usando la libreria pygithub. Per installarla, esegui il seguente comando:

# %pip install pygithub

I percorsi per le istanze di benchmark sono:

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'

Per riprodurre le prestazioni del benchmark per le istanze HUBO, seleziona il backend ibm_marrakesh e imposta direct_qubit_mapping su True nel sotto-dizionario options. L'esempio seguente esegue l'istanza Maxcut con 32 nodi.

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

Casi d'uso​

I casi d'uso tipici per il solver di ottimizzazione sono i problemi di ottimizzazione combinatoria. Puoi risolvere problemi di molti settori come la finanza, la farmaceutica o la logistica. Seguono alcuni esempi.

Se sei interessato ad affrontare un caso d'uso specifico e sviluppare una mappatura dedicata, possiamo assisterti. Contattaci.

Supporto​

Per supporto, contatta support@kipu-quantum.com.

Passi successivi​

Informazioni aggiuntive​

Iskay, come il nome della nostra azienda Kipu Quantum, è una parola peruviana. Sebbene siamo una startup tedesca, queste parole provengono dal paese natale di uno dei nostri co-fondatori, dove il Quipu era una delle primissime macchine di calcolo sviluppate dall'umanità 2000 anni a.C.