Langkau ke kandungan utama
Projek ini dalam fasa beta. Jumpa pepijat? Buat isu GitHub. Ada soalan atau idea? Tanya dalam Discussions — kami suka dengar maklum balas anda!
Bagaimana kualiti terjemahan pada halaman ini?

Optimization Solver: Fungsi Qiskit oleh Q-CTRL Fire Opal

Lihat rujukan API

nota

Qiskit Functions adalah ciri eksperimental yang hanya tersedia untuk pengguna Pelan Premium IBM Quantum®, Pelan Flex, dan Pelan On-Prem (melalui API IBM Quantum Platform). Ia berada dalam status keluaran pratonton dan tertakluk kepada perubahan.

Versi pakej

Kod pada halaman ini dibangunkan menggunakan keperluan berikut. Kami mengesyorkan menggunakan versi ini atau yang lebih baharu.

qiskit-ibm-runtime~=0.47.0
sympy~=1.14.0

Gambaran keseluruhan​

Dengan Fire Opal Optimization Solver, anda boleh menyelesaikan masalah pengoptimuman skala utiliti pada perkakasan kuantum tanpa memerlukan kepakaran kuantum. Cukup masukkan definisi masalah peringkat tinggi, dan Solver akan menguruskan selebihnya. Keseluruhan aliran kerja ini peka hingar dan memanfaatkan Pengurusan Prestasi Fire Opal di sebaliknya. Solver secara konsisten memberikan penyelesaian tepat untuk masalah yang mencabar secara klasik, walaupun pada skala penuh peranti pada QPU IBM® yang terbesar.

Solver fleksibel dan boleh digunakan untuk menyelesaikan masalah pengoptimuman kombinatorial yang ditakrifkan sebagai fungsi objektif atau graf arbitrari. Masalah tidak perlu dipetakan ke topologi peranti. Masalah tanpa kekangan dan dengan kekangan boleh diselesaikan, dengan kekangan dikuatkuasakan sebagai kekangan hard Hamming-weight-1 dan bukannya terma penalti. Contoh-contoh dalam panduan ini menunjukkan cara menyelesaikan masalah pengoptimuman skala utiliti tanpa kekangan dan dengan kekangan menggunakan jenis input Solver yang berbeza. Contoh pertama melibatkan masalah max-cut yang ditakrifkan pada graf 3-Biasa 156 nod, manakala contoh kedua menangani masalah partisioning graf 50 nod yang ditakrifkan oleh fungsi kos.

Untuk mendapatkan akses kepada Optimization Solver, hubungi Q-CTRL.

Penerangan fungsi​

Solver mengoptimumkan dan mengautomatikkan keseluruhan algoritma sepenuhnya, dari penindasan ralat pada peringkat perkakasan hingga pemetaan masalah yang cekap dan pengoptimuman klasik gelung tertutup. Di sebalik tabir, saluran Solver mengurangkan ralat pada setiap peringkat, membolehkan peningkatan prestasi yang diperlukan untuk menskalakan secara bermakna. Aliran kerja asas ini terinspirasi oleh Quantum Approximate Optimization Algorithm (QAOA), yang merupakan algoritma hibrid kuantum-klasik. Untuk ringkasan terperinci aliran kerja Optimization Solver yang penuh, rujuk manuskrip yang diterbitkan.

Visualisasi aliran kerja Optimization Solver

Untuk menyelesaikan masalah umum dengan Optimization Solver:

  1. Takrifkan masalah anda sebagai fungsi objektif, graf, atau rantai spin SparsePauliOp.
  2. Sambung ke fungsi melalui Qiskit Functions Catalog.
  3. Jalankan masalah dengan Solver dan dapatkan semula keputusan.

Format masalah yang diterima​

  • Representasi ungkapan polinomial bagi fungsi objektif. Sebaik-baiknya dibuat dalam Python dengan objek SymPy Poly sedia ada dan diformat menjadi rentetan menggunakan sympy.srepr.

  • Representasi graf bagi jenis masalah tertentu. Graf perlu dibuat menggunakan pustaka networkx dalam Python. Ia kemudian ditukar kepada rentetan menggunakan fungsi networkx nx.readwrite.json_graph.adjacency_data.

  • Representasi rantai spin bagi masalah tertentu. Rantai spin perlu direpresentasikan sebagai objek SparsePauliOp; lihat dokumentasi untuk maklumat lanjut.

Adakah fungsi ini menyokong semua backend IBM?

Jika anda ingin menggunakan backend yang tidak disokong oleh fungsi ini pada masa ini, hubungi Q-CTRL untuk menambah sokongan.

Penanda aras​

Penafian

Prestasi boleh bergantung kepada kedua-dua instans masalah dan langkah pemprosesan seterusnya. Dalam sesetengah kes, sampel klasik dan sampel terjana kuantum mungkin mencapai kualiti penyelesaian akhir yang serupa selepas pascapemprosesan yang setara. Oleh itu, penilaian harus mempertimbangkan keseluruhan aliran kerja pengoptimuman.

Keputusan penanda aras yang diterbitkan menunjukkan bahawa Solver berjaya menyelesaikan masalah dengan lebih 120 qubit, malah mengatasi keputusan yang diterbitkan sebelumnya pada peranti anil kuantum dan ion perangkap. Metrik penanda aras berikut memberikan petunjuk kasar tentang ketepatan dan penskalaan jenis masalah berdasarkan beberapa contoh. Metrik sebenar mungkin berbeza berdasarkan pelbagai ciri masalah, seperti bilangan terma dalam fungsi objektif (ketumpatan) dan lokaliti, bilangan pemboleh ubah, dan tertib polinomial.

"Bilangan qubit" yang ditunjukkan bukan had keras tetapi mewakili ambang kasar di mana anda boleh mengharapkan ketepatan penyelesaian yang sangat konsisten. Saiz masalah yang lebih besar telah berjaya diselesaikan, dan ujian melebihi had ini digalakkan.

Kesambungan qubit arbitrari disokong merentasi semua jenis masalah.

Jenis masalahBilangan qubitContohKetepatanJumlah masa (s)Penggunaan runtime (s)Bilangan iterasi
Masalah kuadratik bersambung jarang156max-cut 3-regular100%176429316
Pengoptimuman binari tertib tinggi156Model kaca spin Ising100%146127216
Masalah kuadratik bersambung padat50max-cut bersambung penuh100%175826812
Masalah dengan kekangan keras50Partisioning graf berwajaran dengan ketumpatan tepi 8%100%107421510

Mulakan​

Pertama, sahkan menggunakan kunci API IBM Quantum anda. Kemudian, pilih Fungsi Qiskit seperti berikut. (Petikan kod ini menganggap anda sudah menyimpan akaun anda ke persekitaran tempatan.)

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

_needed = {"networkx": "networkx", "numpy": "numpy", "qiskit_ibm_catalog": "qiskit-ibm-catalog", "qiskit_ibm_runtime": "qiskit-ibm-runtime", "sympy": "sympy"}
_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(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
solver = catalog.load("q-ctrl/optimization-solver")

Contoh: Pengoptimuman tanpa kekangan​

Jalankan masalah maximum cut (Max-Cut). Contoh berikut menunjukkan keupayaan Solver pada masalah Max-Cut graf 3-regular tidak berwajaran 156 nod, tetapi anda juga boleh menyelesaikan masalah graf berwajaran. Selain qiskit-ibm-catalog, anda juga akan menggunakan pakej berikut untuk menjalankan contoh ini: networkx dan numpy. Anda boleh memasang pakej ini dengan menyahkomenter sel berikut jika anda menjalankan contoh ini dalam notebook menggunakan kernel IPython.

# %pip install networkx numpy

1. Takrifkan masalah​

Anda boleh menjalankan masalah Max-Cut dengan mentakrifkan masalah graf dan menentukan 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 of the previous code cell

Solver menerima rentetan sebagai input definisi masalah.

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

2. Jalankan masalah​

Apabila menggunakan kaedah input berasaskan graf, tentukan jenis masalah.

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

Semak status beban kerja Fungsi Qiskit anda atau dapatkan semula keputusan seperti berikut:

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

# Get job status
print(maxcut_job.status())
34b53970-d95a-4e24-8763-fc6f3d112843
QUEUED

3. Dapatkan semula keputusan​

Dapatkan semula nilai potongan optimum dari kamus keputusan.

nota

Pemetaan pemboleh ubah ke bitstring mungkin telah berubah. Kamus output mengandungi subdiksi variables_to_bitstring_index_map, yang membantu mengesahkan urutan.

# 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: 210.0

Anda boleh mengesahkan ketepatan keputusan dengan menyelesaikan masalah secara klasik menggunakan penyelesai sumber terbuka seperti PuLP jika graf tidak bersambung padat. Masalah berketumpatan tinggi mungkin memerlukan penyelesai klasik lanjutan untuk mengesahkan penyelesaian.

Contoh: Pengoptimuman dengan kekangan​

Contoh max-cut sebelumnya ialah masalah pengoptimuman binari tak terkekang kuadratik yang biasa. Optimization Solver Q-CTRL juga boleh menyelesaikan masalah pengoptimuman terkekang dengan menghantar kekangan tegar terus kepada Solver melalui input constraint, bukannya mengekodkannya sebagai terma penalti dalam fungsi objektif. Solver kini menyokong kekangan Hamming-weight-1: setiap kekangan menentukan sekumpulan pemboleh ubah di mana tepat satu pemboleh ubah mesti sama dengan 1 dan selebihnya mesti sama dengan 0.

Contoh berikut menunjukkan cara membina fungsi kos dan set kekangan tegar untuk masalah pengoptimuman terkekang, pembahagian graf, dengan menetapkan setiap nod dalam graf kepada tepat satu daripada beberapa kumpulan sambil meminimumkan jumlah berat tepi yang kedua-dua hujungnya berada dalam kumpulan yang sama. Selain pakej qiskit-ibm-catalog dan qiskit, anda juga akan menggunakan pakej berikut untuk menjalankan contoh ini: numpy, networkx, dan sympy. Anda boleh memasang pakej ini dengan menyahkomenter sel berikut jika anda menjalankan contoh ini dalam notebook menggunakan kernel IPython.

# %pip install numpy networkx sympy

1. Takrifkan masalah​

Takrifkan masalah pembahagian graf rawak dengan menjana graf dengan nod berwajaran rawak.

import networkx as nx
from sympy import Symbol, 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
graph = nx.erdos_renyi_graph(
node_count, edge_probability, seed=rng_seed, directed=False
)

# add node weights
min_weight = -1.0
max_weight = 1.0
for i in graph.nodes:
weight = (max_weight - min_weight) * _rng.random() + min_weight
graph.add_node(i, weight=weight)

# Optionally, visualize the graph
nx.draw_networkx(graph, nx.kamada_kawai_layout(graph), node_size=200)

Output of the previous code cell

Model pengoptimuman standard untuk pembahagian graf berwajaran boleh dirumuskan seperti berikut. Bahagikan nod graf kepada tiga kumpulan g∈{0,1,2}g \in \{0, 1, 2\}, dan biarkan ni,g=1n_{i,g} = 1 jika nod ii ditetapkan kepada kumpulan gg, dan ni,g=0n_{i,g} = 0 jika sebaliknya. Matlamatnya ialah untuk meminimumkan jumlah berat tepi yang kedua-dua hujungnya ditetapkan kepada kumpulan yang sama, di mana berat tepi (i,j)(i,j) ialah gabungan berat kedua-dua hujungnya, ωi,j=ωi+ωj\omega_{i,j} = \omega_i + \omega_j:

Minimizey=∑(i,j)∈Eωi,j∑gni,g nj,g\textbf{Minimize}\qquad y = \sum_{(i,j)\in E} \omega_{i,j} \sum_{g} n_{i,g}\, n_{j,g}

# Construct the cost function.
group_count = 3
variables = [
Symbol(f"n[{i},{g}]")
for i in range(node_count)
for g in range(group_count)
]
node_group_var = {
(i, g): variables[i * group_count + g]
for i in range(node_count)
for g in range(group_count)
}
cost_function = Poly(0, *variables)

for i, j in graph.edges():
edge_weight = graph.nodes[i]["weight"] + graph.nodes[j]["weight"]
for g in range(group_count):
cost_function += (
edge_weight * node_group_var[(i, g)] * node_group_var[(j, g)]
)

Setiap nod mesti ditetapkan kepada tepat satu daripada tiga kumpulan. Ini adalah kekangan Hamming-weight-1: untuk setiap nod ii, tepat satu daripada ni,0,ni,1,ni,2n_{i,0}, n_{i,1}, n_{i,2} mesti sama dengan 1, dan selebihnya mesti sama dengan 0:

ni,0+ni,1+ni,2=1 for all i∈Vn_{i,0} + n_{i,1} + n_{i,2} = 1 \texttt{ for all } i \in V

Berbanding mengekodkan keperluan ini sebagai terma penalti dalam fungsi kos, hantarkannya terus kepada Solver sebagai kekangan tegar menggunakan input constraint.

# Build the hard constraint: exactly one group per node.
constraint_dict = {
str(tuple(f"n[{i},{g}]" for g in range(group_count))): 1
for i in range(node_count)
}
print(f"Problem constraints: {constraint_dict}")
Problem constraints: {"('n[0,0]', 'n[0,1]', 'n[0,2]')": 1, "('n[1,0]', 'n[1,1]', 'n[1,2]')": 1, "('n[2,0]', 'n[2,1]', 'n[2,2]')": 1, "('n[3,0]', 'n[3,1]', 'n[3,2]')": 1, "('n[4,0]', 'n[4,1]', 'n[4,2]')": 1, "('n[5,0]', 'n[5,1]', 'n[5,2]')": 1, "('n[6,0]', 'n[6,1]', 'n[6,2]')": 1, "('n[7,0]', 'n[7,1]', 'n[7,2]')": 1, "('n[8,0]', 'n[8,1]', 'n[8,2]')": 1, "('n[9,0]', 'n[9,1]', 'n[9,2]')": 1, "('n[10,0]', 'n[10,1]', 'n[10,2]')": 1, "('n[11,0]', 'n[11,1]', 'n[11,2]')": 1, "('n[12,0]', 'n[12,1]', 'n[12,2]')": 1, "('n[13,0]', 'n[13,1]', 'n[13,2]')": 1, "('n[14,0]', 'n[14,1]', 'n[14,2]')": 1, "('n[15,0]', 'n[15,1]', 'n[15,2]')": 1, "('n[16,0]', 'n[16,1]', 'n[16,2]')": 1, "('n[17,0]', 'n[17,1]', 'n[17,2]')": 1, "('n[18,0]', 'n[18,1]', 'n[18,2]')": 1, "('n[19,0]', 'n[19,1]', 'n[19,2]')": 1, "('n[20,0]', 'n[20,1]', 'n[20,2]')": 1, "('n[21,0]', 'n[21,1]', 'n[21,2]')": 1, "('n[22,0]', 'n[22,1]', 'n[22,2]')": 1, "('n[23,0]', 'n[23,1]', 'n[23,2]')": 1, "('n[24,0]', 'n[24,1]', 'n[24,2]')": 1, "('n[25,0]', 'n[25,1]', 'n[25,2]')": 1, "('n[26,0]', 'n[26,1]', 'n[26,2]')": 1, "('n[27,0]', 'n[27,1]', 'n[27,2]')": 1, "('n[28,0]', 'n[28,1]', 'n[28,2]')": 1, "('n[29,0]', 'n[29,1]', 'n[29,2]')": 1, "('n[30,0]', 'n[30,1]', 'n[30,2]')": 1, "('n[31,0]', 'n[31,1]', 'n[31,2]')": 1, "('n[32,0]', 'n[32,1]', 'n[32,2]')": 1, "('n[33,0]', 'n[33,1]', 'n[33,2]')": 1, "('n[34,0]', 'n[34,1]', 'n[34,2]')": 1, "('n[35,0]', 'n[35,1]', 'n[35,2]')": 1, "('n[36,0]', 'n[36,1]', 'n[36,2]')": 1, "('n[37,0]', 'n[37,1]', 'n[37,2]')": 1, "('n[38,0]', 'n[38,1]', 'n[38,2]')": 1, "('n[39,0]', 'n[39,1]', 'n[39,2]')": 1, "('n[40,0]', 'n[40,1]', 'n[40,2]')": 1, "('n[41,0]', 'n[41,1]', 'n[41,2]')": 1, "('n[42,0]', 'n[42,1]', 'n[42,2]')": 1, "('n[43,0]', 'n[43,1]', 'n[43,2]')": 1, "('n[44,0]', 'n[44,1]', 'n[44,2]')": 1, "('n[45,0]', 'n[45,1]', 'n[45,2]')": 1, "('n[46,0]', 'n[46,1]', 'n[46,2]')": 1, "('n[47,0]', 'n[47,1]', 'n[47,2]')": 1, "('n[48,0]', 'n[48,1]', 'n[48,2]')": 1, "('n[49,0]', 'n[49,1]', 'n[49,2]')": 1}
Masalah terkekang separa

Anda tidak perlu menambah setiap pemboleh ubah kepada constraint. Sebarang pemboleh ubah yang ditinggalkan daripada kamus kekal tidak terkekang, jadi anda boleh menggabungkan kumpulan pemboleh ubah yang terkekang tegar dengan pemboleh ubah bebas dalam masalah yang sama.

2. Jalankan masalah​

# Solve the problem
partition_job = solver.run(
problem=srepr(cost_function),
constraint=constraint_dict,
backend_name="ibm_marrakesh", # E.g. "ibm_marrakesh"
)

Semak status beban kerja Fungsi Qiskit anda atau dapatkan semula keputusan seperti berikut:

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

# Get job status
print(partition_job.status())
b8085944-f313-444e-be39-ea61b1b47ebd
QUEUED

3. Dapatkan keputusan​

Dapatkan semula penyelesaian dan analisis keputusan. Kos penyelesaian mewakili jumlah berat tepi yang kedua-dua hujungnya berakhir dalam kumpulan yang sama, jadi kos yang lebih rendah menunjukkan pembahagian graf yang lebih baik.

partition_result = partition_job.result()
qctrl_cost = partition_result["solution_bitstring_cost"]
solution_bitstring = partition_result["solution_bitstring"]

# Print results
print(f"Total weight of same-group edges: {qctrl_cost}")
print(f"Solution bitstring: {solution_bitstring}")
Total weight of same-group edges: -36.5539
Solution bitstring: 100100100100100001100100100100100100100100100100100001010100010100100100100010001001100100100001100001100001010001001010100100100100100010100100100100

Dapatkan sokongan​

Untuk sebarang pertanyaan atau isu, hubungi Q-CTRL.

Log perubahan​

  • 2026-08-10: Menambah sokongan untuk kekangan tegar (Hamming weight 1) melalui input constraint, dan mengemas kini contoh pengoptimuman terkekang untuk menggunakannya.

  • 2026-02-11: Kami kini menyokong ibm_miami

Langkah seterusnya​