Skip to main content
IBM Quantum Platform

Iskay Quantum Optimizer - Una funzione Qiskit di Kipu Quantum

Consulta la documentazione dell'API

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

Panoramica

Con l'Iskay Quantum Optimizer di Kipu Quantum è possibile affrontare complessi problemi di ottimizzazione utilizzando i computer quantistici di IBM®. Questo risolutore sfrutta l'algoritmo bf-DCQO all'avanguardia di Kipu, che richiede solo la funzione obiettivo come input per fornire automaticamente soluzioni ai problemi. Può gestire problemi di ottimizzazione che coinvolgono fino a 156 qubit, consentendo di utilizzare tutti i qubit dei dispositivi quantistici IBM. L'ottimizzatore utilizza una mappatura 1-to-1 tra variabili classiche e qubit, che consente di affrontare problemi di ottimizzazione con un massimo di 156 variabili binarie.

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

Di seguito vengono forniti maggiori dettagli sull'algoritmo utilizzato e una breve guida all'uso della funzione, oltre ai risultati di benchmarking su varie istanze di problemi di diverse dimensioni e complessità.


Descrizione

Optimizer è un'implementazione pronta all'uso di algoritmi di ottimizzazione quantistica all'avanguardia. Risolve problemi di ottimizzazione eseguendo circuiti quantistici altamente compressi su hardware quantistico. Questa compressione si ottiene introducendo termini controdiabatici nell'evoluzione temporale del sistema quantistico. L'algoritmo esegue diverse iterazioni di corse hardware per ottenere le soluzioni finali e le combina con la post-elaborazione. Queste fasi sono perfettamente integrate nel flusso di lavoro di Optimizer e vengono eseguite automaticamente.

Come funziona il Quantum Optimizer?

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

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 alla fine dell'evoluzione. Secondo il teorema adiabatico, questa evoluzione deve essere lenta per garantire che il sistema rimanga nel suo stato fondamentale. La digitalizzazione di questa evoluzione è alla base del calcolo quantistico adiabatico digitalizzato (DQA) e del famoso algoritmo QAOA. Tuttavia, l'evoluzione lenta richiesta non è fattibile per problemi di dimensioni crescenti, poiché comporta un aumento della profondità del circuito. Utilizzando protocolli controdiabatici, è possibile sopprimere le eccitazioni indesiderate che si verificano durante i brevi tempi di evoluzione, pur rimanendo allo stato fondamentale. In questo caso, digitalizzando questo tempo di evoluzione più breve si ottengono circuiti quantistici con una profondità minore e un numero inferiore di porte di entangling.

I circuiti degli algoritmi bf-DCQO utilizzano in genere un numero di porte di entangling fino a dieci volte inferiore rispetto a DQA e da tre a quattro volte inferiore rispetto alle implementazioni standard di QAOA. Grazie al numero ridotto di porte, si verificano meno errori durante l'esecuzione del circuito sull'hardware. Pertanto, l'ottimizzatore non richiede l'uso di tecniche come la soppressione o l'attenuazione degli errori. La loro implementazione nelle versioni future può migliorare ulteriormente la qualità della soluzione.

Sebbene l'algoritmo bf-DCQO utilizzi iterazioni, non è variazionale. Dopo ogni iterazione dell'algoritmo, viene misurata la distribuzione degli stati. La distribuzione ottenuta viene utilizzata per calcolare il cosiddetto campo di polarizzazione. Il campo di polarizzazione consente di iniziare 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 di energia inferiore. In genere, sono sufficienti circa dieci iterazioni per convergere a una soluzione, richiedendo in totale un numero di iterazioni molto inferiore rispetto agli algoritmi variazionali, che sono dell'ordine di circa 100 iterazioni.

L'ottimizzatore combina l'algoritmo bf-DCQO con la classica post-elaborazione. 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 il salto mortale, 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; di conseguenza, è computazionalmente economica. Poiché la post-elaborazione corregge i bitflip locali, compensa gli errori di bit-flip che spesso sono il risultato di imperfezioni hardware e di errori di lettura.

Flusso di lavoro

Segue uno schema del flusso di lavoro del Quantum Optimizer.

Flusso di lavoro
Flusso di lavoro dell'Ottimizzatore Quantistico

Utilizzando il Quantum Optimizer, la soluzione di un problema di ottimizzazione su hardware quantistico può essere ridotta a

  • Formulare la funzione obiettivo del problema
  • Accesso all'ottimizzatore tramite le funzioni di Qiskit
  • Eseguire l'ottimizzatore e raccogliere i risultati

Benchmark

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

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

AR=CCmaxCminCmax,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 CC^{*} è il costo della migliore soluzione trovata. Pertanto, AR=100% significa che è stato ottenuto lo stato fondamentale del problema.

Esempio
Numero di qubit
Rapporto di approssimazione
Tempo totale
Utilizzo del tempo di esecuzione (s)
Numero totale di scatti
Numero di iterazioni
Non ponderato MaxCut28100%1803030k5
Non ponderato MaxCut30100%1803030k5
Non ponderato MaxCut32100%1803030k5
Non ponderato MaxCut80100%4806090k9
Non ponderato MaxCut100100%3306060k6
Non ponderato MaxCut120100%3706060k6
HUBO 1156100%60070100k10
HUBO 2156100%60070100k10
  • Le istanze di MaxCut con 28, 30 e 32 qubit sono state eseguite su ibm_sherbrooke. Le istanze con 80, 100 e 120 sono state eseguite su un processore Heron r2.
  • Anche le istanze di 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 di esecuzione di queste istanze si trova nell' Esempio 3: Istanze di benchmark.


Introduzione

In questa documentazione, illustreremo i passaggi necessari per utilizzare Iskay Quantum Optimizer. Nel corso della procedura mostreremo rapidamente come caricare la funzione dal catalogo e come convertire il problema in un input valido, illustrando al contempo come sperimentare diversi parametri opzionali.

Per un esempio più dettagliato, consulta il tutorial Risolvi il problema della suddivisione del mercato con Iskay Quantum Optimizer di Kipu Quantum, in cui illustriamo l'intero processo di utilizzo di Iskay Solver per affrontare il problema della suddivisione del mercato, che rappresenta una sfida reale nell'allocazione delle risorse in cui i mercati devono essere suddivisi in regioni di vendita equilibrate per soddisfare obiettivi di domanda precisi.

Autenticatevi utilizzando la vostra chiave API, che si trova nella dashboard di IBM Quantum Platform, e selezionate la funzione Qiskit come segue:

Note

Il codice che segue presuppone che tu abbia salvato le tue credenziali. Se non l'hai ancora fatto, segui le istruzioni riportate nella guida "Salva il tuo account IBM Cloud " per effettuare l'autenticazione con la tua chiave 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")

Esempio di configurazione personalizzata

Ecco come puoi configurare Iskay con diverse impostazioni:

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
}

Ottimizzazione dei semi : si noti che seed_transpiler è impostato su None per impostazione predefinita. Ciò consente il processo di ottimizzazione automatica del transpiler. Quando None, il sistema avvierà una prova con più seed e selezionerà quello che produce la migliore profondità del circuito, sfruttando tutta la potenza del max_trials parametro per ogni livello di transpilazione.

Prestazioni a livello di transpilazione : aumentando il numero di max_trials con valori più elevati per transpilation_level si aumenterà inevitabilmente il tempo di transpilazione, ma ciò potrebbe non modificare sempre il circuito finale, poiché ciò dipende in larga misura 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

Consideriamo la funzione di costo nella formulazione di 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 a 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. Creare la funzione obiettivo

Si inizia 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. Eseguire l'ottimizzatore

Risolviamo il problema eseguendo l'ottimizzatore. 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)

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

3. Recupera il risultato

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

print(job.result())

Verrà visualizzato 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'}

Si noti che il dizionario solution visualizza il vettore di risultati (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 di grafi come MaxCut o Maximum independent set sono problemi NP-hard e candidati ideali per testare algoritmi e hardware quantistici. Questo esempio dimostra la risoluzione del problema MaxCut di un grafo 3-regolare con il Quantum Optimizer.

Per eseguire questo esempio è necessario installare il pacchetto networkx oltre al pacchetto qiskit-ibm-catalog. Per installarlo, eseguire il seguente comando:

# %pip install networkx numpy

1. Creare la funzione obiettivo

Si inizia generando un grafo 3-regolare casuale. Per questo grafico, 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. Eseguire l'ottimizzatore

Risolvere il problema eseguendo l'ottimizzatore.

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 bitstring della soluzione ai nodi del grafo originale.

print(job.result())

La soluzione al problema Maxcut è contenuta direttamente nel sottodizionario 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 utilizzando la libreria pygithub . Per installarlo, eseguire il seguente comando:

# %pip install pygithub

I percorsi per le istanze di benchmark sono:

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'

Per riprodurre le prestazioni del benchmark per le istanze HUBO, selezionare il backend ibm_marrakesh e impostare direct_qubit_mapping su True nel sottodizionario options .

L'esempio seguente esegue l'istanza di Maxcut con 150 nodi.

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

Casi di utilizzo

I casi d'uso tipici del solutore di ottimizzazione sono i problemi di ottimizzazione combinatoria. È possibile risolvere problemi di molti settori, come quello finanziario, farmaceutico o logistico. Esempi:

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


Ottenere supporto

Per assistenza, contattare [email protected].


Passi successivi


Ulteriori informazioni

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

Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.