Optimization Solver: Qiskit Function od Q-CTRL Fire Opal
Qiskit Functions jsou experimentální funkce dostupné pouze uživatelům IBM Quantum® Premium Plan, Flex Plan a On-Prem (prostřednictvím IBM Quantum Platform API) Plan. Jsou ve stavu preview verze a mohou se měnit.
Přehled
S Fire Opal Optimization Solver můžeš řešit optimalizační problémy v utility-scale měřítku na kvantovém hardwaru bez potřeby kvantové odbornosti. Jednoduše zadej definici problému na vysoké úrovni a Solver se postará o zbytek. Celý pracovní postup je noise-aware a využívá pod pokličkou Fire Opal Performance Management. Solver konzistentně poskytuje přesná řešení klasicky náročných problémů, a to i v plném rozsahu zařízení na největších IBM® QPU.
Solver je flexibilní a lze jej použít k řešení kombinatorických optimalizačních problémů definovaných jako účelové funkce nebo libovolné grafy. Problémy nemusí být mapovány na topologii zařízení. Řešitelné jsou jak neomezené, tak omezené problémy za předpokladu, že omezení lze formulovat jako penalizační členy. Příklady obsažené v tomto průvodci ukazují, jak vyřešit neomezený a omezený optimalizační problém v utility-scale měřítku pomocí různých typů vstupů Solveru. První příklad zahrnuje problém Max-Cut definovaný na grafu s 156 uzly a 3-regulárním uspořádáním, zatímco druhý příklad řeší problém Minimum Vertex Cover s 50 uzly definovaný pomocí účelové funkce.
Chceš-li získat přístup k Optimization Solver, kontaktuj Q-CTRL.
Popis funkce
Solver plně optimalizuje a automatizuje celý algoritmus – od potlačování chyb na úrovni hardwaru až po efektivní mapování problému a uzavřenou smyčku klasické optimalizace. V zákulisí pipeline Solveru snižuje chyby v každé fázi, což umožňuje zvýšený výkon potřebný pro smysluplné škálování. Základní pracovní postup je inspirován algoritmem Quantum Approximate Optimization Algorithm (QAOA), který je hybridním kvantově-klasickým algoritmem. Podrobný přehled celého pracovního postupu Optimization Solver najdeš v publikovaném rukopisu.
Jak vyřešit obecný problém pomocí Optimization Solver:
- Definuj svůj problém jako účelovou funkci, graf nebo
SparsePauliOpspin chain. - Připoj se k funkci prostřednictvím katalogu Qiskit Functions.
- Spusť problém pomocí Solveru a načti výsledky.
Vstupy a výstupy
Vstupy
| Název | Typ | Popis | Povinné | Výchozí | Příklad |
|---|---|---|---|---|---|
| problem | str nebo SparsePauliOp | Jedno z reprezentací uvedených v části „Přijímané formáty problémů" | Ano | N/A | Poly(2.0*n[0]*n[1] + 2.0*n[0]*n[2] - 3.13520241298341*n[0] + 2.0*n[1]*n[2] - 3.14469748506794*n[1] - 3.18897660121566*n[2] + 6.0, n[0], n[1], n[2], domain='RR') |
| problem_type | str | Název třídy problému; používá se pouze pro definice problémů na základě grafu a spin chain, které jsou omezeny na „maxcut" nebo „spin_chain"; není vyžadováno pro definice problémů s libovolnou účelovou funkcí | Ne | None | "maxcut" |
| backend_name | str | Název Backend, který se má použít | Ne | Nejméně vytížený Backend, ke kterému má tvá instance přístup | "ibm_fez" |
| options | dict | Vstupní možnosti, včetně následujících: (Volitelné) session_id: str; výchozí chování vytvoří novou Session | Ne | None | {"session_id": "cw2q70c79ws0008z6g4g"} |
Přijímané formáty problémů:
- Polynomiální vyjádření účelové funkce. Ideálně vytvořené v Pythonu s existujícím objektem SymPy Poly a formátované do řetězce pomocí sympy.srepr.
- Grafová reprezentace konkrétního typu problému. Graf by měl být vytvořen pomocí knihovny networkx v Pythonu a poté převeden na řetězec pomocí funkce networkx
[nx.readwrite.json_graph.adjacency_data](http://nx.readwrite.json_graph.adjacency_data.). - Reprezentace spin chain konkrétního problému. Spin chain by měl být reprezentován jako objekt
SparsePauliOp; více podrobností najdeš v dokumentaci.
Podporované Backend: Spusť následující kód, abys viděl seznam Backend, které jsou aktuálně podporovány. Pokud tvé zařízení není uvedeno, kontaktuj Q-CTRL a přidej jeho podporu.
# Added by doQumentation — required packages for this notebook
!pip install -q networkx numpy qiskit-ibm-catalog qiskit-ibm-runtime sympy
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
service.backends()
[<IBMBackend('ibm_fez')>,
<IBMBackend('ibm_brisbane')>,
<IBMBackend('ibm_pittsburgh')>,
<IBMBackend('ibm_kingston')>,
<IBMBackend('ibm_torino')>,
<IBMBackend('ibm_marrakesh')>]
Možnosti:
| Název | Typ | Popis | Výchozí |
|---|---|---|---|
| session_id | str | ID existující Qiskit Runtime Session | "cw4r3je6f0t010870y3g" |
| job_tags | list[str] | Seznam tagů úloh | [] |
Výstupy
| Název | Typ | Popis | Příklad |
|---|---|---|---|
| result | dict[str, Any] | Řešení a metadata uvedená v části „Obsah slovníku výsledků" | {'solution_bitstring_cost': 3.0, 'final_bitstring_distribution': {'000001': 100, '000011': 2}, 'iteration_count': 3, 'solution_bitstring': '000001', 'variables_to_bitstring_index_map': {n[1]': 5, 'n[2]': 4, 'n[3]': 3, 'n[4]': 2, 'n[5]': 1}, 'best_parameters': [0.19628831763697097, -1.047052334523102], 'warnings': []} |
Obsah slovníku výsledků:
| Název | Typ | Popis |
|---|---|---|
| solution_bitstring_cost | float | Nejlepší minimální cena napříč všemi iteracemi |
| final_bitstring_distribution | CountsDict | Slovník počtů bitstring přidružený k minimální ceně |
| solution_bitstring | str | Bitstring s nejlepší cenou ve finálním rozložení |
| iteration_count | int | Celkový počet QAOA iterací provedených Solverem |
| variables_to_bitstring_index_map | float | Mapování proměnných na odpovídající bit v bitstringu |
| best_parameters | list[float] | Optimalizované parametry beta a gamma napříč všemi iteracemi |
| warnings | list[str] | Varování vzniklá při kompilaci nebo spuštění QAOA (výchozí hodnota je None) |
Benchmarky
Publikované výsledky benchmarkingu ukazují, že Solver úspěšně řeší problémy s více než 120 qubity a dokonce překonává dříve publikované výsledky na kvantových žíhacích a trapped-ion zařízeních. Následující metriky benchmarku poskytují hrubý přehled o přesnosti a škálování typů problémů na základě několika příkladů. Skutečné metriky se mohou lišit v závislosti na různých vlastnostech problému, jako je počet členů v účelové funkci (hustota) a jejich lokalita, počet proměnných a polynomiální řád.
Uvedený „Počet qubitů" není pevným omezením, ale představuje přibližné prahové hodnoty, kde lze očekávat mimořádně konzistentní přesnost řešení. Větší velikosti problémů byly úspěšně vyřešeny a testování za těmito hranicemi je podporováno.
Libovolná konektivita qubitů je podporována napříč všemi typy problémů.
| Typ problému | Počet qubitů | Příklad | Přesnost | Celkový čas (s) | Využití Runtime (s) | Počet iterací |
|---|---|---|---|---|---|---|
| Řídce propojené kvadratické problémy | 156 | 3-regulární Max-Cut | 100% | 1764 | 293 | 16 |
| Binární optimalizace vyššího řádu | 156 | Ising spin-glass model | 100% | 1461 | 272 | 16 |
| Hustě propojené kvadratické problémy | 50 | Plně propojený Max-Cut | 100% | 1758 | 268 | 12 |
| Omezený problém s penalizačními členy | 50 | Vážené Minimum Vertex Cover s hustotou hran 8 % | 100% | 1074 | 215 | 10 |
Začínáme
Nejprve se ověř pomocí svého IBM Quantum API klíče. Poté vyber Qiskit Function takto. (Tento úryvek předpokládá, že jsi již uložil svůj účet do svého lokálního prostředí.)
from qiskit_ibm_catalog import QiskitFunctionsCatalog
catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# Access Function
solver = catalog.load("q-ctrl/optimization-solver")
Příklad: Neomezená optimalizace
Spusť problém maximálního řezu (Max-Cut). Následující příklad ukazuje schopnosti Solveru na problému Max-Cut s 156uzlovým, 3-regulárním nevážený grafem, ale lze řešit i vážené grafové problémy.
Kromě qiskit-ibm-catalog budeš k tomuto příkladu také potřebovat následující balíčky: networkx a numpy. Tyto balíčky můžeš nainstalovat odkomentováním následující buňky, pokud spouštíš tento příklad v notebooku pomocí IPython kernelu.
# %pip install networkx numpy
1. Definuj problém
Problém Max-Cut můžeš spustit definováním grafového problému a zadáním problem_type='maxcut'.
import networkx as nx
import numpy as np
# Generate a random graph with 156 nodes
maxcut_graph = nx.random_regular_graph(d=3, n=156, seed=8)
# Optionally, visualize the graph
nx.draw_networkx(
maxcut_graph, nx.kamada_kawai_layout(maxcut_graph), node_size=100
)

Solver přijímá řetězec jako vstup definice problému.
# Convert graph to string
problem_as_str = nx.readwrite.json_graph.adjacency_data(maxcut_graph)
2. Spusť problém
Při použití vstupní metody na základě grafu zadej typ problému.
# This cell is hidden from users
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend_name = service.least_busy(n_qubits=156).name
# Solve the problem
maxcut_job = solver.run(
problem=problem_as_str,
problem_type="maxcut",
backend_name=backend_name, # E.g. "ibm_fez"
)
Zkontroluj stav své pracovní zátěže Qiskit Function nebo načti výsledky takto:
# Get job status
print(maxcut_job.status())
QUEUED
3. Načti výsledek
Načti optimální hodnotu řezu ze slovníku výsledků.
variables_to_bitstring_index_map, který pomáhá ověřit pořadí.# Poll for results
maxcut_result = maxcut_job.result()
# Take the absolute value of the solution since the cost function is minimized
qctrl_maxcut = abs(maxcut_result["solution_bitstring_cost"])
# Print the optimal cut value found by the Optimization Solver
print(f"Optimal cut value: {qctrl_maxcut}")
Optimal cut value: 209.0
Přesnost výsledku můžeš ověřit klasickým řešením problému pomocí open-source solverů jako PuLP, pokud graf není hustě propojený. Problémy s vysokou hustotou mohou pro ověření řešení vyžadovat pokročilé klasické solvery.
Příklad: Omezená optimalizace
Předchozí příklad Max-Cut je běžný kvadratický neomezený binární optimalizační problém. Optimization Solver od Q-CTRL lze použít pro různé typy problémů, včetně omezené optimalizace. Libovolné typy problémů můžeš řešit zadáním definice problému reprezentované jako polynom, kde jsou omezení modelována jako penalizační členy.
Následující příklad ukazuje, jak sestavit účelovou funkci pro omezený optimalizační problém – minimum vertex cover (MVC).
Kromě balíčků qiskit-ibm-catalog a qiskit budeš k tomuto příkladu také potřebovat: numpy, networkx a sympy. Tyto balíčky můžeš nainstalovat odkomentováním následující buňky, pokud spouštíš tento příklad v notebooku pomocí IPython kernelu.
# %pip install numpy networkx sympy
1. Definuj problém
Definuj náhodný problém MVC vygenerováním grafu s náhodně váženými uzly.
import networkx as nx
from sympy import symbols, Poly, srepr
# To change the weights, change the seed to any integer.
rng_seed = 18
_rng = np.random.default_rng(rng_seed)
node_count = 50
edge_probability = 0.08
mvc_graph = nx.erdos_renyi_graph(
node_count, edge_probability, seed=rng_seed, directed=False
)
# add node weights
for i in mvc_graph.nodes:
mvc_graph.add_node(i, weight=_rng.random())
# Optionally, visualize the graph
nx.draw_networkx(mvc_graph, nx.kamada_kawai_layout(mvc_graph), node_size=200)

Standardní optimalizační model pro vážené MVC lze formulovat takto. Nejprve musí být přidána penalizace pro každý případ, kdy hrana není spojena s vrcholem v podmnožině. Proto nechť , pokud je vrchol v pokrytí (tj. v podmnožině), a v opačném případě. Zadruhé, cílem je minimalizovat celkový počet vrcholů v podmnožině, což lze vyjádřit následující funkcí:
# Construct the cost function.
variables = symbols([f"n[{i}]" for i in range(node_count)])
cost_function = Poly(0, variables)
for i in mvc_graph.nodes():
weight = mvc_graph.nodes[i].get("weight", 0)
cost_function += variables[i] * weight
Nyní každá hrana v grafu musí obsahovat alespoň jeden koncový bod z pokrytí, což lze vyjádřit nerovností:
Každý případ, kdy hrana není spojena s vrcholem pokrytí, musí být penalizován. To lze vyjádřit v účelové funkci přidáním penalizačního členu ve tvaru , kde je kladná penalizační konstanta. Neomezená alternativa k omezené nerovnosti pro vážené MVC je tedy:
# Add penalty term.
penalty_constant = 2
for i, j in mvc_graph.edges():
cost_function += penalty_constant * (
1 - variables[i] - variables[j] + variables[i] * variables[j]
)
2. Spusť problém
# Solve the problem
mvc_job = solver.run(
problem=srepr(cost_function),
backend_name=backend_name, # E.g. "ibm_fez"
)
Zkontroluj stav své pracovní zátěže Qiskit Function nebo načti výsledky takto:
print(mvc_job.status())
3. Získej výsledek
Načti řešení a analyzuj výsledky. Protože tento problém má vážené uzly, řešení není jednoduše minimální počet pokrytých uzlů. Místo toho cena řešení představuje součet vah vrcholů, které jsou zahrnuty ve vertex cover. Reprezentuje celkové „náklady" nebo „váhu" pokrytí všech hran v grafu pomocí vybraných vrcholů.
mvc_result = mvc_job.result()
qctrl_cost = mvc_result["solution_bitstring_cost"]
# Print results
print(f"Solution cost: {qctrl_cost}")
Solution cost: 10.248198273708624
Získej podporu
Máš-li jakékoli dotazy nebo problémy, kontaktuj Q-CTRL.
Další kroky
- Požádej o přístup k Q-CTRL Optimization Solver.
- Vyzkoušej tutoriál Řešení binárních optimalizačních problémů vyššího řádu pomocí Optimization Solver od Q-CTRL.
- Přečti si Sachdeva, N., et al. (2024). Quantum optimization using a 127-qubit gate-model IBM quantum computer can outperform quantum annealers for nontrivial binary optimization problems. arXiv preprint arXiv:2406.01743.
- Přečti si Loco, D., et al. (2026). Practical protein-pocket hydration-site prediction for drug discovery on a quantum computer. arXiv preprint arXiv:2512.08390.
- Přečti si případovou studii Mazda.
- Přečti si případovou studii Network Rail.
- Přečti si případovou studii Australian Army.
- Přečti si případovou studii Transport for New South Wales.