SQOA Solver - una Qiskit Function di JIJ
Consulta il riferimento API.
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.
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 del suo qubit. QRAO usa anche gli operatori e . 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, ) 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.
| QAOA | SQOA | |
|---|---|---|
| Qubit per variabili binarie | Un qubit contiene fino a tre variabili. Il numero esatto dipende dalla struttura del problema | |
| Uso della QPU | Stima ripetutamente l'energia di circuiti parametrizzati all'interno di un ciclo di ottimizzazione classico | Campiona solo stringhe di bit. Sulla QPU non viene addestrato alcun parametro del circuito |
| Dai campioni a una soluzione | Seleziona la migliore stringa di bit misurata | Diagonalizza 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
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:
dove è il miglior valore dell'obiettivo trovato e è 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.
| Istanza | Numero di variabili | Numero di qubit | Rapporto di approssimazione | Tempo totale (secondi) | Tempo QPU (secondi) |
|---|---|---|---|---|---|
| maxcut_384_nodes | 384 | 129 | 98.5% | 62.1 | 12.0 |
| gen200_p0-9_44 | 200 | 67 | 100% | 38.0 | 12.0 |
| es60fst02 | 186 | 42 | 100% | 24.7 | 12.0 |
| es60fst04 | 162 | 29 | 100% | 17.9 | 12.0 |
| maxcut_150_nodes | 150 | 51 | 100% | 23.1 | 12.0 |
| sloane_1dc_128 | 128 | 37 | 93.8% | 19.1 | 12.0 |
| sloane_2dc_128 | 128 | 8 | 100% | 12.3 | 11.5 |
| C125-9 | 125 | 43 | 100% | 22.3 | 12.0 |
| es60fst01 | 123 | 12 | 100% | 13.6 | 12.0 |
| es60fst03 | 113 | 26 | 100% | 14.9 | 12.0 |
| sloane_1dc_64 | 64 | 16 | 100% | 13.4 | 11.9 |
| chesapeake | 39 | 13 | 100% | 13.1 | 12.0 |
| football | 35 | 6 | 100% | 12.5 | 12.0 |
| karate | 34 | 2 | 100% | 6.2 | 6.0 |
| ibm32 | 32 | 11 | 100% | 12.9 | 12.0 |
| farm | 17 | 4 | 100% | 8.5 | 8.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:
-
Scrivi il modello. Crea un
OptimizationProblem, aggiungi variabili decisionali binarie e imposta l'obiettivo ed eventuali vincoli. -
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. -
Converti in dizionario. Passa il QUBO alla funzione di supporto
to_problem_dict()definita nella sezione successiva e passa il risultato asolver.run()comeproblem, insieme avariable_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 a ciascun vertice di un grafo per indicarne il lato del taglio. Un arco è tagliato quando i suoi estremi si trovano su lati diversi, quindi la dimensione del taglio è:
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 chiavix_i, doveiè l'indice della variabile (ad esempio,x_3). -
objective_valueefeasiblesono l'obiettivo e l'ammissibilità di tale assegnazione, valutati sul dizionario inviato. -
metadatacontienesolver_infoeresource_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.Solutioncanonica insolver_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(),feasibleviene 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 unommx.v1.Instancenella stringa che passi comeproblem. -
to_ommx_solution()decodifica laommx.v1.Solutioncanonica 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 assegna a ciascun vertice. Un arco è tagliato quando , quindi la dimensione del taglio è:
JijModeling non fornisce una variabile decisionale di spin nativa, e SQOA Solver accetta variabili binarie QUBO. Pertanto, dichiara e definisci l'espressione a valori di spin 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:
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
- Richiedi una prova gratuita di SQOA Solver compilando questo modulo.
- Consulta il riferimento API di questa Qiskit Function.
- Prova un esempio end-to-end nel tutorial sul problema dell'insieme indipendente massimo.
- Scopri come modellare problemi di ottimizzazione con qiskit-addon-opt-mapper.
- Scopri come modellare e scambiare problemi di ottimizzazione con JijModeling e OMMX.
- Leggi l'articolo su SQOA-QR [1] per saperne di più sul framework SQOA.
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