Lumaktaw sa pangunahing nilalaman

Optimization Solver: Isang Qiskit Function ng Q-CTRL Fire Opal

tala

Ang Qiskit Functions ay isang experimental na feature na available lamang sa mga gumagamit ng IBM Quantumยฎ Premium Plan, Flex Plan, at On-Prem (sa pamamagitan ng IBM Quantum Platform API) Plan. Nasa preview release status ang mga ito at maaaring magbago.

Pangkalahatang-ideyaโ€‹

Gamit ang Fire Opal Optimization Solver, maaari kang magsulat ng utility-scale na mga optimization problem sa quantum hardware nang hindi kailangan ng malalim na kaalaman sa quantum computing. I-input lang ang mataas na antas na depinisyon ng problema, at ang Solver ang bahala sa lahat. Ang buong workflow ay may kamalayan sa ingay at gumagamit ng Fire Opal's Performance Management sa likod ng sistema. Patuloy na nagbibigay ang Solver ng tumpak na solusyon sa mga problemang mahirap lutasin nang klasikal, kahit sa pinakamataas na sukat ng pinakamalalaking IBMยฎ QPU.

Flexible ang Solver at magagamit para sa mga combinatorial optimization problem na tinukoy bilang objective function o arbitrary graph. Hindi kailangang i-map ang mga problema sa device topology. Parehong malulutas ng unconstrained at constrained na mga problema, basta ma-formulate ang mga constraint bilang penalty term. Ipinapakita ng mga halimbawa sa gabay na ito kung paano lutasin ang isang unconstrained at isang constrained na utility-scale optimization problem gamit ang iba't ibang uri ng Solver input. Ang unang halimbawa ay isang Max-Cut problem na tinukoy sa isang 156-node, 3-Regular na graph, habang ang pangalawa ay isang 50-node na Minimum Vertex Cover problem na tinukoy ng isang cost function.

Para makakuha ng access sa Optimization Solver, makipag-ugnayan sa Q-CTRL.

Paglalarawan ng functionโ€‹

Ganap na ino-optimize at ino-automate ng Solver ang buong algorithm, mula sa error suppression sa hardware level hanggang sa mahusay na problem mapping at closed-loop classical optimization. Sa likod ng sistema, binabawasan ng pipeline ng Solver ang mga error sa bawat yugto, na nagbibigay ng mas mataas na performance na kailangan para makapag-scale nang maayos. Ang pinagbabatayang workflow ay inspirado ng Quantum Approximate Optimization Algorithm (QAOA), na isang hybrid quantum-classical na algorithm. Para sa detalyadong buod ng buong Optimization Solver workflow, tingnan ang nai-publish na manuskrito.

Visualization ng Optimization Solver workflow

Para malutas ang isang pangkalahatang problema gamit ang Optimization Solver:

  1. Tukuyin ang iyong problema bilang objective function, graph, o SparsePauliOp spin chain.
  2. Kumonekta sa function sa pamamagitan ng Qiskit Functions Catalog.
  3. Patakbuhin ang problema gamit ang Solver at kunin ang mga resulta.

Mga input at outputโ€‹

Mga Inputโ€‹

PangalanUriPaglalarawanKinakailanganDefaultHalimbawa
problemstr o SparsePauliOpIsa sa mga representasyon na nakalista sa ilalim ng "Tinatanggap na mga format ng problema"OoN/APoly(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_typestrPangalan ng klase ng problema; ginagamit lamang para sa graph at spin chain na depinisyon ng problema, na limitado sa "maxcut" o "spin_chain"; hindi kailangan para sa arbitrary objective function na depinisyon ng problemaHindiNone"maxcut"
backend_namestrPangalan ng backend na gagamitinHindiPinaka-idle na backend na may access ang iyong instance"ibm_fez"
optionsdictMga input option, kasama ang sumusunod: (Opsyonal) session_id: str; ang default na gawi ay gumagawa ng bagong SessionHindiNone{"session_id": "cw2q70c79ws0008z6g4g"}

Tinatanggap na mga format ng problema:

  • Polynomial expression na representasyon ng isang objective function. Mas mainam na gawin ito sa Python gamit ang isang umiiral na SymPy Poly object at i-format sa string gamit ang sympy.srepr.
  • Graph na representasyon ng isang partikular na uri ng problema. Dapat gawin ang graph gamit ang networkx library sa Python. Pagkatapos ay i-convert ito sa string gamit ang networkx function na [nx.readwrite.json_graph.adjacency_data](http://nx.readwrite.json_graph.adjacency_data.).
  • Spin chain na representasyon ng isang partikular na problema. Dapat ireprensenta ang spin chain bilang SparsePauliOp object; tingnan ang dokumentasyon para sa karagdagang detalye.

Mga sinusuportahang backend: Patakbuhin ang sumusunod na code para makita ang listahan ng mga backend na kasalukuyang sinusuportahan. Kung hindi nakalista ang iyong device, makipag-ugnayan sa Q-CTRL para idagdag ang suporta.

# 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')>]

Mga Opsyon:

PangalanUriPaglalarawanDefault
session_idstrIsang umiiral na Qiskit Runtime session ID"cw4r3je6f0t010870y3g"
job_tagslist[str]Isang listahan ng mga job tag[]

Mga Outputโ€‹

PangalanUriPaglalarawanHalimbawa
resultdict[str, Any]Solusyon at metadata na nakalista sa ilalim ng "Mga nilalaman ng result dictionary"{'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': []}

Mga nilalaman ng result dictionary:

PangalanUriPaglalarawan
solution_bitstring_costfloatAng pinakamababang halaga ng cost sa lahat ng iteration
final_bitstring_distributionCountsDictAng bitstring counts dictionary na kaugnay ng pinakamababang cost
solution_bitstringstrBitstring na may pinakamahusay na cost sa panghuling distribusyon
iteration_countintAng kabuuang bilang ng QAOA iteration na isinagawa ng Solver
variables_to_bitstring_index_mapfloatAng pagma-map mula sa mga variable patungo sa katumbas na bit sa bitstring
best_parameterslist[float]Ang mga na-optimize na beta at gamma parameter sa lahat ng iteration
warningslist[str]Ang mga babala na nagawa habang nagko-compile o nagpapatakbo ng QAOA (default ay None)

Mga Benchmarkโ€‹

Ipinapakita ng mga nai-publish na resulta ng benchmarking na matagumpay na nireresulba ng Solver ang mga problema na may mahigit 120 qubit, at kahit pa nakakalampas sa mga dating nai-publish na resulta sa quantum annealing at trapped-ion na mga device. Ang mga sumusunod na benchmark metric ay nagbibigay ng magaspang na indikasyon ng katumpakan at scaling ng mga uri ng problema batay sa ilang halimbawa. Maaaring mag-iba ang aktwal na mga metric batay sa iba't ibang katangian ng problema, tulad ng bilang ng mga term sa objective function (density) at ang kanilang locality, bilang ng mga variable, at polynomial order.

Ang "Bilang ng mga qubit" na nakaindika ay hindi isang mahigpit na limitasyon kundi kumakatawan sa mga magaspang na threshold kung saan maaari kang umasa ng lubhang pare-pareho na katumpakan ng solusyon. Matagumpay na nareresulba ang mga mas malalaking sukat ng problema, at hinihikayat ang pagsubok na lagpas sa mga limitasyong ito.

Sinusuportahan ang arbitrary qubit connectivity sa lahat ng uri ng problema.

Uri ng problemaBilang ng mga qubitHalimbawaKatumpakanKabuuang oras (s)Paggamit ng runtime (s)Bilang ng mga iteration
Sparsely-connected na mga quadratic problem1563-regular Max-Cut100%176429316
Higher-order binary optimization156Ising spin-glass model100%146127216
Densely-connected na mga quadratic problem50Fully-connected Max-Cut100%175826812
Constrained na problema na may penalty term50Weighted Minimum Vertex Cover na may 8% edge density100%107421510

Magsimulaโ€‹

Una, mag-authenticate gamit ang iyong IBM Quantum API key. Pagkatapos, piliin ang Qiskit Function tulad ng sumusunod. (Ipinapalagay ng snippet na ito na na-save mo na ang iyong account sa iyong lokal na kapaligiran.)

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

# Access Function
solver = catalog.load("q-ctrl/optimization-solver")

Halimbawa: Unconstrained na optimizationโ€‹

Patakbuhin ang maximum cut (Max-Cut) na problema. Ipinapakita ng sumusunod na halimbawa ang kakayahan ng Solver sa isang 156-node, 3-regular na unweighted graph Max-Cut problem, ngunit maaari ka ring magsulat ng mga weighted graph problem. Bukod sa qiskit-ibm-catalog, gagamitin mo rin ang mga sumusunod na package para patakbuhin ang halimbawang ito: networkx at numpy. Maaari mong i-install ang mga package na ito sa pamamagitan ng pag-uncomment ng sumusunod na cell kung pinapatakbo mo ang halimbawang ito sa isang notebook gamit ang IPython kernel.

# %pip install networkx numpy

1. Tukuyin ang problemaโ€‹

Maaari kang magpatakbo ng Max-Cut problem sa pamamagitan ng pagde-define ng graph problem at pagtukoy ng 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
)

Output ng nakaraang code cell

Tumatanggap ang Solver ng string bilang input ng depinisyon ng problema.

# Convert graph to string
problem_as_str = nx.readwrite.json_graph.adjacency_data(maxcut_graph)

2. Patakbuhin ang problemaโ€‹

Kapag gumagamit ng graph-based na paraan ng input, tukuyin ang uri ng problema.

# 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"
)

Suriin ang status ng iyong Qiskit Function workload o kunin ang mga resulta tulad ng sumusunod:

# Get job status
print(maxcut_job.status())
QUEUED

3. Kunin ang resultaโ€‹

Kunin ang pinakamainam na halaga ng cut mula sa results dictionary.

tala
Maaaring nagbago ang pagma-map ng mga variable sa bitstring. Ang output dictionary ay naglalaman ng variables_to_bitstring_index_map sub-dictionary, na tumutulong sa pag-verify ng pagkakasunod-sunod.
# 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

Maaari mong ma-verify ang katumpakan ng resulta sa pamamagitan ng paglutas ng problema nang klasikal gamit ang mga open-source solver tulad ng PuLP kung hindi masyadong siksik ang koneksyon ng graph. Para sa mga problemang may mataas na density, maaaring kailangan ng mas advanced na classical solver para ma-validate ang solusyon.

Halimbawa: Constrained na optimizationโ€‹

Ang nakaraang Max-Cut example ay isang karaniwang quadratic unconstrained binary optimization problem. Maaaring gamitin ang Q-CTRL's Optimization Solver para sa iba't ibang uri ng problema, kasama na ang constrained optimization. Maaari kang magsulat ng arbitrary na uri ng problema sa pamamagitan ng pag-input ng depinisyon ng problema bilang polynomial kung saan ang mga constraint ay kinakatawan bilang penalty term.

Ipinapakita ng sumusunod na halimbawa kung paano bumuo ng cost function para sa isang constrained optimization problem, minimum vertex cover (MVC). Bukod sa mga package na qiskit-ibm-catalog at qiskit, gagamitin mo rin ang mga sumusunod na package para patakbuhin ang halimbawang ito: numpy, networkx, at sympy. Maaari mong i-install ang mga package na ito sa pamamagitan ng pag-uncomment ng sumusunod na cell kung pinapatakbo mo ang halimbawang ito sa isang notebook gamit ang IPython kernel.

# %pip install numpy networkx sympy

1. Tukuyin ang problemaโ€‹

Tukuyin ang isang random na MVC problem sa pamamagitan ng paglikha ng graph na may mga node na may random na timbang.

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)

Output ng nakaraang code cell

Ang isang karaniwang optimization model para sa weighted MVC ay maaaring i-formulate tulad ng sumusunod. Una, kailangan magdagdag ng penalty para sa anumang kaso kung saan ang isang edge ay hindi konektado sa isang vertex sa subset. Kaya, hayaan ang ni=1n_i = 1 kung ang vertex ii ay nasa cover (ibig sabihin, nasa subset) at ni=0n_i = 0 kung hindi. Pangalawa, ang layunin ay i-minimize ang kabuuang bilang ng mga vertex sa subset, na maaaring irepresenta ng sumusunod na function:

Minimizey=โˆ‘iโˆˆVฯ‰ini\textbf{Minimize}\qquad y = \sum_{i\in V} \omega_i n_i

# 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

Ngayon, ang bawat edge sa graph ay dapat may kasamang kahit isang endpoint mula sa cover, na maaaring ipahayag bilang inequality:

ni+njโ‰ฅ1ย forย allย (i,j)โˆˆEn_i + n_j \ge 1 \texttt{ for all } (i,j)\in E

Ang anumang kaso kung saan ang isang edge ay hindi konektado sa vertex ng cover ay dapat parusahan. Maaari itong irepresenta sa cost function sa pamamagitan ng pagdaragdag ng penalty na may anyo P(1โˆ’niโˆ’nj+ninj)P(1-n_i-n_j+n_i n_j) kung saan ang PP ay isang positibong penalty constant. Kaya, ang isang unconstrained na alternatibo sa constrained inequality para sa weighted MVC ay:

Minimizey=โˆ‘iโˆˆVฯ‰ini+P(โˆ‘(i,j)โˆˆE(1โˆ’niโˆ’nj+ninj))\textbf{Minimize}\qquad y = \sum_{i\in V}\omega_i n_i + P(\sum_{(i,j)\in E}(1 - n_i - n_j + n_i n_j))

# 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. Patakbuhin ang problemaโ€‹

# Solve the problem
mvc_job = solver.run(
problem=srepr(cost_function),
backend_name=backend_name, # E.g. "ibm_fez"
)

Suriin ang status ng iyong Qiskit Function workload o kunin ang mga resulta tulad ng sumusunod:

print(mvc_job.status())

3. Kunin ang resultaโ€‹

Kunin ang solusyon at suriin ang mga resulta. Dahil ang problemang ito ay may mga weighted node, ang solusyon ay hindi simpleng pinakamaliit na bilang ng mga node na sakop. Sa halip, ang halaga ng solusyon ay kumakatawan sa kabuuan ng mga timbang ng mga vertex na kasama sa vertex cover. Kinakatawan nito ang kabuuang "gastos" o "timbang" ng pagsaklaw sa lahat ng mga edge sa graph gamit ang mga napiling vertex.

mvc_result = mvc_job.result()
qctrl_cost = mvc_result["solution_bitstring_cost"]

# Print results
print(f"Solution cost: {qctrl_cost}")
Solution cost: 10.248198273708624

Makakuha ng suportaโ€‹

Para sa anumang katanungan o isyu, makipag-ugnayan sa Q-CTRL.

Mga susunod na hakbangโ€‹