Vai al contenuto principale
Questo progetto è in fase beta. Hai trovato un bug? Apri una issue su GitHub. Hai una domanda o un'idea? Chiedi su GitHub Discussions — apprezziamo il tuo feedback!
Com'è la qualità della traduzione su questa pagina?

SQOA Solver - una Qiskit Function di JIJ

Consulta il riferimento API.

nota

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 versione preliminare (preview) e soggette a modifiche.

Panoramica​

Con SQOA Solver di JIJ puoi risolvere grandi problemi di ottimizzazione combinatoria sui computer quantistici IBM®. Il solver si basa sul Sampling-based Quantum Optimization Algorithm with Quantum Relaxation (SQOA-QR) [1]. A differenza degli algoritmi quantistici che usano una mappatura uno a uno tra variabili decisionali classiche e qubit, SQOA Solver è in grado di gestire problemi di ottimizzazione con più variabili del numero di qubit disponibili sugli attuali dispositivi quantistici. Il suo design basato sul campionamento lo rende inoltre meno sensibile al rumore fisico dell'attuale hardware quantistico. Insieme, queste caratteristiche rendono SQOA Solver adatto ai problemi di ottimizzazione in questa fase del calcolo quantistico.

Il solver gestisce problemi di Quadratic Unconstrained Binary Optimization (QUBO) forniti come formulazione matematica classica e mappa automaticamente la formulazione classica nel contesto quantistico. Puoi anche convertire problemi con vincoli in problemi senza vincoli usando il metodo della penalità.

Le sezioni seguenti descrivono il flusso di lavoro del solver, i risultati dei benchmark ed esempi end-to-end che modellano i problemi con qiskit-addon-opt-mapper e, facoltativamente, Open Mathematical prograMming eXchange (OMMX). OMMX è un formato di dati aperto e un SDK che semplifica lo scambio di problemi di ottimizzazione tra strumenti software.

Descrizione​

SQOA Solver implementa il Sampling-based Quantum Optimization Algorithm with Quantum Relaxation (SQOA-QR) e lo circonda con pre-elaborazione e post-elaborazione classiche. Questa sezione spiega il framework SQOA e in cosa si differenzia dal Quantum Approximate Optimization Algorithm (QAOA).

La figura seguente mostra uno schema del flusso di lavoro di SQOA Solver. Schema del flusso di lavoro di SQOA Solver, dalla pre-elaborazione classica attraverso il campionamento SQOA fino alla post-elaborazione e alla ricerca locale

Il framework SQOA​

SQOA è un framework basato sul campionamento per l'ottimizzazione combinatoria [1]. Combina due tecniche: il Quantum Random Access Optimization (QRAO) [2], che codifica il problema in un rilassamento quantistico, e la diagonalizzazione quantistica basata su campioni (SQD) [3], nota anche come quantum-selected configuration interaction (QSCI) [4], che usa il computer quantistico solo per campionare stringhe di bit e trova lo stato di bassa energia su un computer classico. SQOA è un framework nel senso che fissa questa combinazione ma lascia i dettagli a ciascuna implementazione, ad esempio come le variabili vengono assegnate ai qubit e quali circuiti generano i campioni.

  • Rilassamento quantistico con QRAO. QAOA e altri approcci basati su Ising rappresentano ogni variabile binaria con l'operatore ZZ del suo qubit. QRAO usa anche gli operatori XX e YY. Con un codice di accesso casuale quantistico (QRAC) (3,1), fino a tre variabili binarie condividono un qubit e ciascuna variabile è rappresentata da un diverso operatore di Pauli.

    Il QUBO diventa così un Hamiltoniano rilassato che richiede meno qubit dell'Hamiltoniano di Ising. Le variabili che interagiscono nel QUBO devono essere collocate su qubit diversi. Se condividessero un qubit, il prodotto dei loro operatori di Pauli si ridurrebbe a un singolo operatore su quel qubit (ad esempio, XY=iZXY = iZ) e l'Hamiltoniano rilassato non rappresenterebbe più la loro interazione.

    L'assegnazione delle variabili ai qubit determina quindi sia il numero di qubit sia la qualità del rilassamento, e SQOA Solver progetta questa assegnazione nella sua pre-elaborazione.

  • Diagonalizzazione quantistica basata su campioni (SQD). Il computer quantistico prepara prima uno stato quantistico che ha sovrapposizione con gli stati a bassa energia dell'Hamiltoniano rilassato e poi ne campiona le stringhe di bit. Un computer classico proietta l'Hamiltoniano rilassato sul sottospazio generato dalle stringhe di bit campionate e lo diagonalizza per approssimare lo stato fondamentale.

    Poiché l'Hamiltoniano rilassato non è diagonale, la diagonalizzazione combina le stringhe di bit campionate in una sovrapposizione. Con un Hamiltoniano di Ising diagonale, ogni stringa di bit è già un autostato e la diagonalizzazione si limiterebbe a selezionare il campione migliore. Lo stesso approccio è stato applicato a problemi su larga scala in chimica quantistica.

Lo stato fondamentale approssimato ottenuto con SQD non corrisponde direttamente a una soluzione classica del problema originale, quindi la soluzione classica deve essere decodificata da esso. Poiché questo stato viene calcolato su un computer classico, la decodifica, chiamata arrotondamento (rounding), è una post-elaborazione classica. SQOA Solver usa tecniche di decodifica progettate per ottenere euristicamente soluzioni classiche migliori.

La tabella seguente confronta SQOA con QAOA, un comune approccio variazionale alla stessa classe di problemi.

 QAOASQOA
Qubit per nn variabili binariennUn qubit contiene fino a tre variabili. Il numero esatto dipende dalla struttura del problema
Uso della QPUStima ripetutamente l'energia di circuiti parametrizzati all'interno di un ciclo di ottimizzazione classicoCampiona solo stringhe di bit. Sulla QPU non viene addestrato alcun parametro del circuito
Dai campioni a una soluzioneSeleziona la migliore stringa di bit misurataDiagonalizza l'Hamiltoniano rilassato nel sottospazio campionato su un computer classico e arrotonda lo stato risultante

Attorno a SQOA-QR, SQOA Solver aggiunge un'elaborazione classica. La pre-elaborazione fissa le variabili i cui valori ottimali possono essere determinati in anticipo e progetta l'assegnazione delle variabili ai qubit. La post-elaborazione affina la soluzione arrotondata con una ricerca locale, che puoi disattivare con postprocessing_level=0.

Benchmark​

Avvertenza

Le prestazioni possono dipendere sia dall'istanza del problema sia dai passaggi di elaborazione successivi. In alcuni casi, i campioni classici e quelli generati quantisticamente potrebbero raggiungere una qualità finale della soluzione simile dopo una post-elaborazione equivalente. La valutazione dovrebbe quindi considerare l'intero flusso di lavoro di ottimizzazione.

Le seguenti metriche di benchmark forniscono un'indicazione generale della qualità della soluzione, della compressione dei qubit e del tempo di esecuzione per dimensioni e strutture di problema selezionate. La tabella elenca una selezione di istanze di Maximum Independent Set della Quantum Optimization Benchmarking Library (QOBLIB) e due istanze MaxCut 3-regolari. Puoi caricare le istanze QOBLIB come oggetti ommx.v1.Instance, insieme alle loro soluzioni ottimali, usando il pacchetto ommx-quantum-benchmarks.

Ogni istanza è stata eseguita 10 volte su un processore IBM Heron r2. Number of qubits conta i qubit effettivamente usati sull'hardware dopo la pre-elaborazione e la codifica QRAC. Il rapporto di compressione dipende dall'istanza. Approximation ratio (AR) indica la qualità della migliore soluzione trovata nelle 10 esecuzioni:

AR=CbestCopt,\mathrm{AR} = \frac{C_{\textrm{best}}}{C_{\textrm{opt}}},

dove CbestC_{\textrm{best}} è il miglior valore dell'obiettivo trovato e CoptC_{\textrm{opt}} è il valore ottimo noto dell'obiettivo. Tutte le istanze sono problemi di massimizzazione con un valore ottimo positivo, quindi AR è al massimo 100%, e 100% nella colonna Approximation ratio indica che il solver ha trovato una soluzione ottimale. Total time è il tempo medio combinato di QPU e CPU per esecuzione. QPU time è l'utilizzo medio di IBM Quantum Compute per esecuzione.

IstanzaNumero di variabiliNumero di qubitRapporto di approssimazioneTempo totale (secondi)Tempo QPU (secondi)
maxcut_384_nodes38412998.5%62.112.0
gen200_p0-9_4420067100%38.012.0
es60fst0218642100%24.712.0
es60fst0416229100%17.912.0
maxcut_150_nodes15051100%23.112.0
sloane_1dc_1281283793.8%19.112.0
sloane_2dc_1281288100%12.311.5
C125-912543100%22.312.0
es60fst0112312100%13.612.0
es60fst0311326100%14.912.0
sloane_1dc_646416100%13.411.9
chesapeake3913100%13.112.0
football356100%12.512.0
karate342100%6.26.0
ibm323211100%12.912.0
farm174100%8.58.0

Per iniziare​

Trova le informazioni di accesso per questa Qiskit Function nel Qiskit Functions Catalog.

Questa sezione mostra come autenticarti e caricare la funzione, e come preparare un problema nel formato dizionario accettato da SQOA Solver usando OptimizationProblem di qiskit-addon-opt-mapper. Gli esempi che seguono eseguono la funzione e leggono il risultato.

Autenticarsi e caricare la funzione​

Per prima cosa, autenticati con la tua chiave API di IBM Quantum. (Il codice seguente presuppone che tu abbia già salvato il tuo account nel tuo ambiente locale.) Poi crea un client del catalogo come segue:

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"jijmodeling": "jijmodeling", "networkx": "networkx", "ommx": "ommx", "qiskit_addon_opt_mapper": "qiskit-addon-opt-mapper", "qiskit_ibm_catalog": "qiskit-ibm-catalog"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

# verify that you have access to the function
catalog.list()
[QiskitFunction(jij/sqoa-solver)]
solver = catalog.load("jij/sqoa-solver")

Preparare l'input con qiskit-addon-opt-mapper​

Questa guida modella i problemi con la classe OptimizationProblem di qiskit-addon-opt-mapper. SQOA Solver accetta un problema QUBO come dizionario di coefficienti nel formato tupla-stringa usato dalle funzioni di ottimizzazione IBM, quindi ogni esempio di questa guida segue lo stesso schema di preparazione lato client:

  1. Scrivi il modello. Crea un OptimizationProblem, aggiungi variabili decisionali binarie e imposta l'obiettivo ed eventuali vincoli.

  2. Converti in QUBO. Converti il problema con OptimizationProblemToQubo, che aggiunge gli eventuali vincoli all'obiettivo come termini di penalità e restituisce un problema di minimizzazione equivalente senza vincoli.

  3. Converti in dizionario. Passa il QUBO alla funzione di supporto to_problem_dict() definita nella sezione successiva e passa il risultato a solver.run() come problem, insieme a variable_type="binary".

SQOA Solver minimizza sempre un problema in formato dizionario, il che corrisponde al problema di minimizzazione restituito da OptimizationProblemToQubo. Per un problema di massimizzazione, l'objective_value restituito è quindi l'opposto dell'obiettivo originale. Per leggere il risultato in termini del problema originale, valuta l'assegnazione restituita con OptimizationProblem, come mostrano gli esempi. Per i dettagli sul formato dizionario, consulta Accepted problem formats nel riferimento API.

# %pip install qiskit-addon-opt-mapper

Definisci la seguente funzione di supporto una sola volta e riutilizzala in ogni esempio. Converte il QUBO restituito da OptimizationProblemToQubo nel formato dizionario. Le chiavi usano gli indici delle variabili del QUBO, quindi le chiavi della soluzione x_0, x_1 e così via nel risultato corrispondono a tali indici. Ogni variabile riceve una voce lineare, anche con coefficiente zero, in modo che la soluzione restituita copra tutte le variabili.

from qiskit_addon_opt_mapper import OptimizationProblem
from qiskit_addon_opt_mapper.converters import OptimizationProblemToQubo

def to_problem_dict(qubo: OptimizationProblem) -> dict[str, float]:
"""Convert a QUBO from OptimizationProblemToQubo to the SQOA Solver dictionary format."""
objective = qubo.objective
payload = {"()": objective.constant}
# Keep every variable in the problem, even with a zero linear coefficient.
payload.update({f"({i},)": 0.0 for i in range(qubo.get_num_vars())})
for i, coefficient in objective.linear.to_dict().items():
payload[f"({i},)"] += coefficient
for (i, j), coefficient in objective.quadratic.to_dict().items():
# Fold a binary diagonal term x_i * x_i = x_i into the linear term.
key = f"({i},)" if i == j else f"({i}, {j})"
payload[key] = payload.get(key, 0.0) + coefficient
return {key: float(value) for key, value in payload.items()}

Esempio 1: MaxCut su un grafo 3-regolare​

Molti problemi su grafi, come MaxCut, sono NP-hard e sono candidati naturali per l'ottimizzazione quantistica. Installa networkx come dipendenza aggiuntiva per eseguire questo esempio:

# %pip install networkx

1. Scrivi il modello​

Assegna una variabile binaria xv∈{0,1}x_v \in \{0, 1\} a ciascun vertice di un grafo G=(V,E)G = (V, E) per indicarne il lato del taglio. Un arco è tagliato quando i suoi estremi si trovano su lati diversi, quindi la dimensione del taglio è:

Cut(x)=∑(u,v)∈E(xu+xv−2xuxv).\mathrm{Cut}(x) = \sum_{(u,v) \in E} \left(x_u + x_v - 2 x_u x_v\right).

Questo obiettivo è già un QUBO senza vincoli, quindi OptimizationProblemToQubo si limita a trasformare la massimizzazione nella minimizzazione equivalente e lascia invariate le variabili. La classe applicativa Maxcut in qiskit_addon_opt_mapper.applications costruisce lo stesso modello con Maxcut(G).to_optimization_problem().

import networkx as nx

G = nx.random_regular_graph(3, 40, seed=42)

linear = {v: 0 for v in G.nodes}
quadratic = {}
for u, v in G.edges:
linear[u] += 1
linear[v] += 1
quadratic[(u, v)] = -2

maxcut = OptimizationProblem("MaxCut")
maxcut.binary_var_list(G.number_of_nodes(), name="x")
maxcut.maximize(linear=linear, quadratic=quadratic)

2. Esegui il solver​

Converti il modello in un QUBO e poi in un dizionario, quindi invialo. problem e variable_type sono obbligatori. backend_name è facoltativo. Quando viene omesso o è None, la funzione seleziona la QPU operativa meno occupata disponibile per la tua istanza.

Il dizionario options accetta shots, seed, session, postprocessing_level e job_tags. Per descrizioni e valori predefiniti, consulta il riferimento API.

qubo = OptimizationProblemToQubo().convert(maxcut)

job = solver.run(
problem=to_problem_dict(qubo),
variable_type="binary",
backend_name="ibm_fez",
options={
"shots": 4096,
"seed": 42,
},
)

3. Recupera il risultato​

job.result() restituisce un dizionario con quattro chiavi:

  • solution è l'assegnazione completa delle variabili, con chiavi x_i, dove i è l'indice della variabile (ad esempio, x_3).

  • objective_value e feasible sono l'obiettivo e l'ammissibilità di tale assegnazione, valutati sul dizionario inviato.

  • metadata contiene solver_info e resource_usage.

Poiché il QUBO è la forma di minimizzazione di MaxCut, objective_value è l'opposto della dimensione del taglio. Valuta l'assegnazione sull'OptimizationProblem originale per leggere direttamente la dimensione del taglio.

result = job.result()

x = [result["solution"][f"x_{i}"] for i in range(maxcut.get_num_vars())]
print(f"Cut value: {maxcut.objective.evaluate(x)}")
print(f"Nodes on side 1: {[v for v, value in enumerate(x) if value > 0.5]}")
Cut value: 55.0
Nodes on side 1: [5, 7, 9, 11, 14, 16, 17, 19, 21, 23, 24, 26, 30, 31, 33, 34, 36, 37, 38]

4. Controlla l'utilizzo delle risorse​

result["metadata"]["resource_usage"] riporta il tempo trascorso in ciascuna fase di esecuzione. Le fasi diverse da RUNNING: EXECUTING_QPU riportano CPU_TIME, il tempo reale (wall-clock) della fase in secondi, quando è disponibile.

La fase RUNNING: EXECUTING_QPU riporta QPU_TIME, l'utilizzo della QPU di tutti i job Quantum Compute dell'esecuzione, se l'utilizzo finale è disponibile per ogni job. Per i dettagli, consulta il riferimento API.

for phase, metrics in result["metadata"]["resource_usage"].items():
line = f"{phase:36s}"
if "CPU_TIME" in metrics:
line += f" CPU {metrics['CPU_TIME']:8.1f} s"
if "QPU_TIME" in metrics:
line += f" QPU {metrics['QPU_TIME']:8.1f} s"
print(line)
RUNNING: MAPPING CPU 3.2 s
RUNNING: OPTIMIZING_FOR_HARDWARE CPU 5.0 s
RUNNING: WAITING_FOR_QPU CPU 1.1 s
RUNNING: EXECUTING_QPU QPU 3.0 s
RUNNING: POST_PROCESSING CPU 0.9 s

Esempio 2: Convertire un problema con vincoli in QUBO​

SQOA Solver accetta problemi senza vincoli. Questo esempio mostra come convertire un problema con vincoli in un QUBO con OptimizationProblemToQubo e rimappare il risultato sulle variabili del problema originale.

selection = OptimizationProblem("ConstrainedExample")
selection.binary_var_list(2, name="x")
selection.maximize(linear={"x0": 1, "x1": 1})
selection.linear_constraint({"x0": 1, "x1": 1}, "<=", 1, name="at_most_one")

print(selection.prettyprint())
Problem name: ConstrainedExample

Maximize
x0 + x1

Subject to
Linear constraints (1)
x0 + x1 <= 1 'at_most_one'

Binary variables (2)
x0 x1

OptimizationProblemToQubo aggiunge i vincoli all'obiettivo come termini di penalità e converte il problema in minimizzazione. Il peso di penalità appropriato dipende dal problema.

Dopo l'esecuzione, interpret() rimappa l'assegnazione del QUBO sulle variabili del problema originale.

Valuta l'obiettivo e l'ammissibilità sul problema originale. Per un problema in formato dizionario, il campo feasible del risultato si riferisce solo al dominio delle variabili, perché il dizionario non ha vincoli.

converter = OptimizationProblemToQubo(penalty=4.0)
qubo = converter.convert(selection)

job = solver.run(
problem=to_problem_dict(qubo),
variable_type="binary",
backend_name="ibm_fez",
)
result = job.result()

x_qubo = [result["solution"][f"x_{i}"] for i in range(qubo.get_num_vars())]
x = converter.interpret(x_qubo)
print("Objective:", selection.objective.evaluate(x))
print("Feasible:", selection.is_feasible(x))
print("x values:", x)
Objective: 1.0
Feasible: True
x values: [1. 0.]

Esempio 3: Inviare un'istanza OMMX​

SQOA Solver accetta anche un ommx.v1.Instance dell'SDK OMMX, che conserva insieme al problema i nomi delle variabili, i pedici e i metadati di conversione. Rispetto a un dizionario, un input OMMX offre i seguenti vantaggi:

  • Il risultato contiene anche la ommx.v1.Solution canonica in solver_info["ommx_solution"].

  • objective_value è valutato nel senso dell'istanza, quindi l'obiettivo di un problema di massimizzazione non viene negato.

  • Per un'istanza convertita sul posto con Instance.to_qubo(), feasible viene valutato rispetto ai vincoli originali.

Questo esempio costruisce il modello MaxCut dell'Esempio 1 con JijModeling, un modellatore di ottimizzazione matematica che compila i modelli in istanze OMMX. Installa JijModeling, che installa anche il pacchetto ommx:

# %pip install "jijmodeling~=2.8.0"

SQOA Solver scambia i dati OMMX come stringhe Base64 standard con padding. Definisci le seguenti funzioni di supporto per questa conversione:

  • to_problem_payload() serializza un ommx.v1.Instance nella stringa che passi come problem.

  • to_ommx_solution() decodifica la ommx.v1.Solution canonica dal risultato.

import base64

from ommx.v1 import Instance, Solution

def to_problem_payload(instance: Instance) -> str:
"""Serialize an OMMX instance into the `problem` string for SQOA Solver."""
return base64.b64encode(instance.to_bytes()).decode()

def to_ommx_solution(result: dict) -> Solution:
"""Decode the canonical OMMX solution from a SQOA Solver result."""
payload = result["metadata"]["solver_info"]["ommx_solution"]
return Solution.from_bytes(base64.b64decode(payload, validate=True))

1. Scrivi il modello con JijModeling​

La consueta formulazione di MaxCut con spin su un grafo G=(V,E)G = (V, E) assegna sv∈{−1,+1}s_v \in \{-1, +1\} a ciascun vertice. Un arco è tagliato quando susv=−1s_u s_v = -1, quindi la dimensione del taglio è:

Cut⁡(s)=∑(u,v)∈E1−susv2.\operatorname{Cut}(s) = \sum_{(u,v) \in E} \frac{1 - s_u s_v}{2}.

JijModeling non fornisce una variabile decisionale di spin nativa, e SQOA Solver accetta variabili binarie QUBO. Pertanto, dichiara bv∈{0,1}b_v \in \{0, 1\} e definisci l'espressione a valori di spin sv=1−2bvs_v = 1 - 2b_v all'interno del modello. Con questa espressione, l'obiettivo resta nella forma di spin standard e l' istanza compilata rimane un QUBO binario.

import jijmodeling as jm

@jm.Problem.define("MaxCut", sense=jm.ProblemSense.MAXIMIZE)
def maxcut_model(problem: jm.DecoratedProblem):
V = problem.Natural() # number of nodes
E = problem.Graph(dtype=V) # edge list
b = problem.BinaryVar(shape=(V,))
s = 1 - 2 * b # spin-valued expression

problem += jm.sum((1 - s[u] * s[v]) / 2 for u, v in E)

Se visualizzi maxcut_model in un notebook, mostra la seguente formulazione:

Problem ⁣:MaxCutmax⁡∑⟨u,v⟩∈E1−(1−2⋅b)u⋅(1−2⋅b)v2whereDecision Variables:bi∈{0,1}a 1-dim array of binary decision variables∀i∈{0,…,V−1}Placeholders:Ei∈V×Va 1-dim array of placeholders with elements in V×V∀i∈{0,…,len_at(E,0)−1}V∈Na scalar placeholder in N\begin{array}{rl} \text{Problem}\colon &\text{MaxCut}\\ \displaystyle \max &\displaystyle \sum _{\left\langle u,v\right\rangle \in E}{\frac{1-{\left(1-2\cdot b\right)}_{u}\cdot {\left(1-2\cdot b\right)}_{v}}{2}}\\ &\\ \text{where}&\\ &\text{Decision Variables:}\\ &\qquad \begin{alignedat}{2}{b}_{i}&\in \left\{0,1\right\}&\qquad &\text{a }1\text{-dim array of }\text{binary}\text{ decision variables}\\ &\forall i\in \left\{0,\ldots ,V-1\right\}&&\\ \end{alignedat}\\ &\\ &\text{Placeholders:}\\ &\qquad \begin{alignedat}{2}{E}_{i}&\in V\times V&\qquad &\text{a }1\text{-dim array of placeholders with elements in }V\times V\\ &\forall i\in \left\{0,\ldots ,\mathop{\mathtt{len\_{}at}}\left(E,0\right)-1\right\}&&\\ &&&\\ V&\in \mathbb{N}&\qquad &\text{a scalar placeholder in }\mathbb{N}\\ \end{alignedat}\end{array}

2. Compila l'istanza ed esegui il solver​

Associa il grafo dell'Esempio 1 per compilare un ommx.v1.Instance e invialo con variable_type="binary". Un'istanza OMMX viene sempre inviata come problema binario.

instance = maxcut_model.eval(
{"V": G.number_of_nodes(), "E": [list(edge) for edge in G.edges]}
)

job = solver.run(
problem=to_problem_payload(instance),
variable_type="binary",
backend_name="ibm_fez",
)

3. Recupera il risultato​

Per un input OMMX, objective_value è la dimensione del taglio e to_ommx_solution() decodifica la soluzione canonica in modo che tu possa leggere l'assegnazione per nome di variabile.

result = job.result()
print(f"Cut value: {result['objective_value']}")

solution = to_ommx_solution(result)
b_values = solution.extract_decision_variables("b")
print(
f"Nodes on side 1: {sorted(v for (v,), value in b_values.items() if value > 0.5)}"
)
Cut value: 55.0
Nodes on side 1: [5, 7, 9, 11, 14, 16, 17, 19, 21, 23, 24, 26, 30, 31, 33, 34, 36, 37, 38]

Ottenere supporto​

Per assistenza, scrivi a info@j-ij.com.

Prossimi passi​

Raccomandazioni

Riferimenti​

[1] Matsuyama, H., & Yamashiro, Y. (2025). Sampling-based quantum optimization algorithm with quantum relaxation. 2025 IEEE International Conference on Quantum Computing and Engineering (QCE), 1, 2323–2333. DOI, arXiv:2504.12629

[2] Fuller, B., Hadfield, C., Glick, J. R., Imamichi, T., Itoko, T., Thompson, R. J., Jiao, Y., Kagele, M. M., Blom-Schieber, A. W., Raymond, R., et al. (2024). Approximate solutions of combinatorial problems via quantum relaxations. IEEE Transactions on Quantum Engineering, 5, 1–15. DOI, arXiv:2111.03167

[3] Robledo-Moreno, J., Motta, M., Haas, H., Javadi-Abhari, A., Jurcevic, P., Kirby, W., et al. (2025). Chemistry beyond the scale of exact diagonalization on a quantum-centric supercomputer. Science Advances, 11(25), eadu9991. DOI, arXiv:2405.05068

[4] Kanno, K., Kohda, M., Imai, R., Koh, S., Mitarai, K., Mizukami, W., & Nakagawa, Y. O. (2026). Quantum-selected configuration interaction: Classical diagonalization of Hamiltonians in subspaces selected by quantum computers. Physical Review Research, 8(2), 023268. DOI, arXiv:2302.11320