Перейти до основного вмісту
Цей проєкт у бета-версії. Знайшов(-ла) помилку? Відкрити issue на GitHub. Є запитання чи ідея? Запитати в Discussions — будемо раді твоєму відгуку!
Яка якість перекладу на цій сторінці?

Constrained Quantum Optimizer — функція Qiskit від Aqarios

Див. довідник API

примітка

Qiskit Functions — це експериментальна можливість, доступна лише користувачам IBM Quantum® Premium Plan, Flex Plan та On-Prem (через IBM Quantum Platform API) Plan. Вони мають статус попереднього релізу (preview) і можуть змінюватися.

Огляд​

За допомогою Constrained Quantum Optimizer від Aqarios ти можеш розв'язувати задачі обмеженої бінарної оптимізації на квантовому апаратному забезпеченні IBM® без ручного переформулювання та відображення схем. Просто надай задачу у вигляді LP-файлу, MPS-файлу або Luna Model. Функція автоматично виконує переформулювання, синтез схем, транспіляцію та виконання на апаратному забезпеченні. Розв'язувач використовує ітеративний теплий старт [1] алгоритму FlexQAOA — розширення Quantum Approximate Optimization Algorithm (QAOA), що нативно підтримує обмеження.

Оптимізатор орієнтований на бінарні задачі з обмеженнями. Зокрема, обмеження типу one-hot та обмеження типу set-packing можуть нативно виконуватися за допомогою XY-мікшерів. Інші типи обмежень автоматично переформулюються у вигляді штрафних доданків.

Підтримувані типи змінних

Функція розв'язує лише дискретні задачі. Кожна змінна рішення має бути бінарною або цілочисельною з явно заданими нижньою та верхньою межами, щоб її можна було закодувати в кубіти. Неперервні (дійсні) змінні не підтримуються: модель, що їх містить, відхиляється з кодом помилки 4710.

Опис​

Застереження

Продуктивність може залежати як від конкретного екземпляра задачі, так і від наступних етапів обробки. У деяких випадках класичні вибірки та вибірки, згенеровані квантовим комп'ютером, можуть досягати подібної кінцевої якості розв'язку після еквівалентної постобробки. Тому оцінювання має враховувати весь робочий процес оптимізації.

Constrained Quantum Optimizer реалізує Iterative warm-start XY-mixer QAOA (IWS-QAOA) [1]. Алгоритм виконує схеми QAOA з фіксованими кутами на квантовому апаратному забезпеченні та оновлює початкові ймовірності теплого старту кожної схеми на основі результатів вимірювань попередньої ітерації. Навчання варіаційних параметрів не потрібне; натомість обирається фіксована параметризація з лінійною рампою.

Використовуючи XY-мікшери для забезпечення обмежень one-hot, можна суттєво покращити якість розв'язку для задач з обмеженнями, оскільки простір пошуку практично звужується до меншого допустимого підпростору — і при цьому не додається зайва складність через штрафні доданки в ландшафті оптимізації.

Робочий процес​

Робочий процес функції описано нижче:

  1. Попередня обробка: перед синтезом схеми оптимізатор аналізує структуру обмежень вхідної задачі:

    • Попередня обробка графа: якщо це застосовно до задачі, вона аналізується як граф, у якому ребра визначають зв'язок між змінними. Такий аналіз графа дає змогу здійснити два вдосконалення на етапі попередньої обробки. По-перше, окремі обмеження можуть бути об'єднані в одне велике обмеження за допомогою злиття клік (clique merging), щоб вони представлялися єдиним XY-мікшером. По-друге, змінні, що мають лише одного сусіда, можуть бути детерміновано зафіксовані, що зменшує розмір і складність задачі.

    • Розв'язання обмежень: препроцесор обробляє кожне обмеження окремо: якщо обмеження є обмеженням типу one-hot, воно може бути забезпечене за допомогою XY-мікшерів. Якщо це обмеження типу set-packing, його спочатку перетворюють на обмеження типу one-hot. Обмеження рівності обробляються за допомогою квадратичних штрафів, а обмеження нерівності — за допомогою незбалансованого штрафування.

    • Виведення штрафу: обмеження, які не можуть бути виражені як обмеження рівності типу one-hot, перетворюються на штрафні доданки. Оптимізатор автоматично визначає силу штрафу на основі структури задачі.

  2. Ітеративний теплий старт: оптимізатор запускає кілька паралельних ланцюжків теплого старту. Кожен ланцюжок містить розподіл ймовірностей на множині присвоєнь значень змінним, який використовується як початкова ймовірність схеми QAOA (стан теплого старту). На кожній ітерації ланцюжок виконує вибірку зі квантової схеми, застосовує класичну постобробку та оновлює свій розподіл на основі частоти появи вибірок. У ході ітерацій це зосереджує пошук на високоякісних розв'язках без циклу варіаційної оптимізації.

Кількість ланцюжків (num_parallel), загальний бюджет шотів на ланцюжок (total_shots) і кількість повторень QAOA (reps) є основними параметрами для балансування якості розв'язку та часу виконання.

Workflow diagram of the Constrained Quantum Optimizer

Бенчмарки​

Наведені нижче бенчмарки показують, що функція Qiskit Constrained Quantum Optimizer здатна знаходити високоякісні допустимі розв'язки задач оптимізації з обмеженнями, що містять значно понад 100 бінарних змінних. Точність — це відношення знайденого значення цільової функції до відомого оптимуму. Час виконання — це фактичний (реальний) час від виклику функції до отримання результату. Використання QPU — це оплачуваний час обчислень Quantum Compute.

Було розглянуто дві задачі: задачу найбільшої незалежної множини (MIS) та Max-kk-Cut, яка є розширенням добре відомої задачі MaxCut на більш ніж дві категорії. Max-kk-Cut також є оптимізаційним відповідником задачі розпізнавання (задачі прийняття рішення) про розфарбування графа (якщо всі ребра розрізано, граф є kk-розфарбовуваним).

ЗадачаЗмінніОбмеженняКубітиТочністьДопустимістьЗагальний час виконання (с)Використання QPU (с)Загальна кількість шотів
MIS es60fst02186280124100.0%True940.2147.025.0k
MIS sloane_2dc_128128517374100.0%True347.6106.012.5k
Max-3-Cut Karate Club99339998.7%True279.5166.025.0k
Max-4-Cut Karate Club13233132100.0%True258.3200.025.0k

Примітки до бенчмарків​

  • Наведені вище результати отримано на процесорі ibm_marrakesh Heron r2 з параметрами за замовчуванням та увімкненим use_session. Для екземпляра sloane_2dc_128 використовувалося значення total_shots=12500.

  • Зменшена кількість кубітів для екземплярів MIS (74 та 124 порівняно з 128 та 186 змінними) відображає фіксацію змінних під час попередньої обробки.

  • Екземпляри задачі MIS взято з Quantum Optimization Benchmarking Library. - Екземпляром для задачі Max-kk-Cut є граф Zachary Karate Club, який має хроматичне число 5.

Початок роботи​

У цьому посібнику показано базове використання Constrained Quantum Optimizer: як завантажити функцію та виконати прості задачі. Для більш детального навчального матеріалу див. Find the Maximum Independent Set with the Aqarios Constrained Quantum Optimizer.

Автентифікуйся за допомогою ключа API IBM Quantum та CRN екземпляра, а потім завантаж функцію з каталогу.

примітка

Наведений нижче код передбачає, що ти вже зберіг свої облікові дані. Щоб налаштувати їх, дотримуйся інструкцій у розділі Save your IBM Cloud account credentials.

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

_needed = {"luna_model": "luna-model", "networkx": "networkx", "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(aqarios/constrained-quantum-optimizer)]
# Load the function
optimizer = catalog.load("aqarios/constrained-quantum-optimizer")
# Check the list of backends you have access to
catalog.backends()
[<IBMBackend('ibm_pittsburgh')>,
<IBMBackend('ibm_boston')>,
<IBMBackend('ibm_phoenix')>,
<IBMBackend('ibm_fez')>,
<IBMBackend('ibm_miami')>,
<IBMBackend('ibm_marrakesh')>,
<IBMBackend('ibm_kingston')>]
# Select the backend you want to use
backend = catalog.backend("ibm_phoenix")

Приклад 1: проста задача з обмеженнями​

Перший приклад показує, як використовувати функцію з LP-файлами — поширеним форматом специфікації задач оптимізації, що використовується в дослідженні операцій. Ти сформулюєш таку довільну задачу оптимізації з п'ятьма бінарними змінними xi∈{0,1}x_i \in \{0,1\} за двох обмежень:

min⁡x1x2+2x2x3−x3x4−2x4x5−2x1x3−4x2x5s.t.x1+x2+x3≤1x3−x4+x5=0 \min x_1 x_2 + 2 x_2 x_3 - x_3 x_4 - 2 x_4 x_5 - 2 x_1 x_3 - 4 x_2 x_5 \\ \text{s.t.}\quad x_1 + x_2 + x_3 \leq 1 \\ \quad x_3 - x_4 + x_5 = 0

1. Сформулюйте задачу​

Викладіть математичний вираз безпосередньо у форматі LP-рядка, як показано нижче:

lp_str = """\\Problem name: Example
Minimize
obj: [ 2 x_1 x_2 + 4 x_2 x_3 - 2 x_3 x_4 - 4 x_4 x_5 - 4 x_1 x_3 - 8 x_2 x_5 ] / 2
Subject To
c1: x_1 + x_2 + x_3 <= 1
c2: x_3 - x_4 + x_5 = 0
Binaries
x_1 x_2 x_3 x_4 x_5
End
"""

Зауважте, що [ ... ] / 2 є обов'язковою нотацією для квадратичних цільових функцій відповідно до стандарту LP.

2. Запустіть оптимізатор​

Розв'яжи задачу за допомогою оптимізатора.

# Set up low-resource options for the simple problem
options = {"total_shots": 2000, "num_parallel": 5, "use_session": True}

# Dispatch the job
job_1 = optimizer.run(
problem=lp_str, backend_name=backend.name, options=options
)

print(f"Job ID: {job_1.job_id}")
Job ID: 2e06a3a8-7c29-4c76-94d7-194293363f4a
# Monitor the job status
job_1.status()
'RUNNING: WAITING_FOR_QPU'

3. Отримайте результат​

Результат надає розв'язок, що зіставляє імена змінних з відповідними присвоєннями значень.

result = job_1.result()

result
{'solutions': [{'x_1': 0, 'x_2': 1, 'x_3': 0, 'x_4': 1, 'x_5': 1}],
'solution_bitstrings': ['01011'],
'raw_energy': -6.0,
'objective_value': -6.0,
'feasible': True,
'metadata': {'resource_usage': {'RUNNING: MAPPING': {'CPU': 5.405},
'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU': 9.902},
'RUNNING: WAITING_FOR_QPU': {'CPU': 25.456},
'RUNNING: EXECUTING_QPU': {'CPU': 25.202},
'RUNNING: POST_PROCESSING': {'CPU': 6.481}},
'circuit_metrics': {'before_transpilation': {'num_qubits': 6,
'gate_count': 42,
'depth': 15,
'two_qubit_gate_count': 12,
'two_qubit_gate_depth': 7,
'operations': {'rz': 12,
'p': 8,
'ry': 7,
'rzz': 4,
'cx': 3,
'xx_plus_yy': 3,
'global_phase': 2,
'cry': 2,
'x': 1}},
'after_transpilation': {'num_qubits': 6,
'gate_count': 254,
'depth': 100,
'two_qubit_gate_count': 48,
'two_qubit_gate_depth': 33,
'operations': {'rz': 78, 'sx': 122, 'cz': 48, 'measure': 6, 'x': 0}}},
'solver_info': {'variable_mapping': {'x_1': 0,
'x_2': 1,
'x_3': 2,
'x_4': 3,
'x_5': 4}}}}

Поле solutions у словнику результату містить усі знайдені вироджені найкращі розв'язки у вигляді словників, які зіставляють ім'я кожної змінної з її значенням. Ті самі розв'язки також повертаються як бітові рядки в solution_bitstrings; metadata.solver_info.variable_mapping показує, яка позиція символу в бітовому рядку належить якій змінній. Разом з даними розв'язку надаються objective_value, прапорець feasible та додаткові metadata.

Приклад 2: найбільша незалежна множина​

Задача найбільшої незалежної множини (MIS) полягає в пошуку найбільшої підмножини вершин графа такої, що жодні дві вершини цієї підмножини не з'єднані ребром. У цьому прикладі MIS розв'язується для регулярного графа з 12 вузлами. Докладніше про цю задачу та більший приклад див. у навчальному матеріалі.

Задачу побудовано за допомогою qiskit-addon-opt-mapper. За потреби встановіть необхідні пакети:

# %pip install networkx qiskit-addon-opt-mapper

Крок 1: визначте задачу​

Побудуй випадковий 3-регулярний граф і створи задачу оптимізації MIS. Кожен вузол графа стає бінарною змінною, а кожне ребро вводить обмеження, яке гарантує, що обрано щонайбільше одну з його кінцевих вершин.

import networkx as nx
from qiskit_addon_opt_mapper.applications import IndependentSet
from qiskit_addon_opt_mapper.translators import to_docplex_mp

# 12-node random 3-regular graph
G = nx.random_regular_graph(3, 12, seed=7)

# Build MIS problem and export as LP string
mis = IndependentSet(G)
mis_problem = mis.to_optimization_problem()
lp_str = to_docplex_mp(mis_problem).export_as_lp_string()

print(lp_str)
\ This file has been generated by DOcplex
\ ENCODING=ISO-8859-1
\Problem name: Independent set

Maximize
obj: x_0 + x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9 + x_10 + x_11
Subject To
c0: x_0 + x_4 <= 1
c1: x_0 + x_9 <= 1
c2: x_0 + x_8 <= 1
c3: x_1 + x_2 <= 1
c4: x_1 + x_7 <= 1
c5: x_1 + x_3 <= 1
c6: x_2 + x_4 <= 1
c7: x_2 + x_11 <= 1
c8: x_3 + x_10 <= 1
c9: x_3 + x_11 <= 1
c10: x_4 + x_5 <= 1
c11: x_5 + x_10 <= 1
c12: x_5 + x_6 <= 1
c13: x_6 + x_8 <= 1
c14: x_6 + x_7 <= 1
c15: x_7 + x_9 <= 1
c16: x_8 + x_11 <= 1
c17: x_9 + x_10 <= 1

Bounds
0 <= x_0 <= 1
0 <= x_1 <= 1
0 <= x_2 <= 1
0 <= x_3 <= 1
0 <= x_4 <= 1
0 <= x_5 <= 1
0 <= x_6 <= 1
0 <= x_7 <= 1
0 <= x_8 <= 1
0 <= x_9 <= 1
0 <= x_10 <= 1
0 <= x_11 <= 1

Binaries
x_0 x_1 x_2 x_3 x_4 x_5 x_6 x_7 x_8 x_9 x_10 x_11
End

Крок 2: запустіть оптимізатор​

Розв'яжи задачу за допомогою оптимізатора.

options = {"total_shots": 2000, "use_session": True}

# Dispatch the job
job_2 = optimizer.run(
problem=lp_str, backend_name=backend.name, options=options
)

print(f"Job ID: {job_2.job_id}")
Job ID: f041431c-b42e-4627-afe5-522fea61faf6
# Monitor the job status
job_2.status()
'QUEUED'

Крок 3: отримайте та інтерпретуйте результати​

Насамкінець отримаємо розв'язок і перевіримо його правильність.

result = job_2.result()

print(f"Feasible: {result['feasible']}")
print(f"Independent set size: {int(result['objective_value'])}")

# Extract the selected nodes
solution = result["solutions"][0]
independent_set = [
int(k.split("_")[1]) for k, v in solution.items() if v == 1
]
print(f"Selected nodes: {sorted(independent_set)}")

# Verify no two selected nodes share an edge
conflicts = [
(u, v)
for u, v in G.edges()
if u in independent_set and v in independent_set
]
print(f"Edge conflicts: {conflicts}")
Feasible: True
Independent set size: 5
Selected nodes: [1, 4, 6, 9, 11]
Edge conflicts: []

Приклад 3: розфарбування графа у 3 кольори (Max-3-Cut)​

Задача Max-kk-Cut розбиває вершини графа на kk груп так, щоб максимізувати кількість ребер, кінцеві точки яких належать до різних груп. Для k=3k = 3 це еквівалентно пошуку розфарбування у 3 кольори, яке максимізує кількість міжколірних ребер.

Формально, кожному вузлу i∈Vi \in V призначається одна з kk груп за допомогою бінарних змінних xi,cx_{i,c} для кольору c∈{1,…,k}c \in \{1, \ldots, k\}. Обмеження one-hot ∑cxi,c=1\sum_c x_{i,c} = 1 для кожного вузла забезпечує унікальне присвоєння. Цільова функція максимізує кількість міжгрупових ребер:

min⁡∑(u,v)∈E∑cxu,c xv,cs.t.∑cxi,c=1∀i∈V\min \sum_{(u,v) \in E} \sum_c x_{u,c} \, x_{v,c}\\ \text{s.t.} \sum_{c} x_{i,c} = 1 \quad \forall i \in V

Обмеження one-hot є ідеальними для XY-мікшерів, які оптимізатор обробляє нативно.

У цьому прикладі використовується граф Zachary Karate Club (34 вузли, 78 ребер), а модель будується за допомогою Luna Model. За потреби встановіть необхідні пакети:

# %pip install networkx matplotlib luna-model

Крок 1: визначте задачу​

Спочатку згенеруйте бінарні змінні за допомогою пакета luna-model. Потім визначте цільову функцію та додайте обмеження до моделі.

import networkx as nx
from luna_model import Model, quicksum

k = 3
G = nx.karate_club_graph()

# Instantiate the Model object
model = Model(name="Max-3-Cut")

# Add binary variables
x = model.add_variables("x", shape=(G.number_of_nodes(), k))

# Add the objective by using the numpy dot abstraction
model.objective = quicksum(x[i].dot(x[j]) for i, j in G.edges)

# Bulk-add the one-hot constraints
model.add_constraints(x.sum(axis=1) == 1)

# Encode the model to send via API
model_enc = model.encode_b64()

Крок 2: запустіть оптимізатор​

Розв'яжи задачу за допомогою оптимізатора.

options = {"use_session": True}

# Dispatch the job
job_3 = optimizer.run(
problem=model_enc, backend_name=backend.name, options=options
)

print(f"Job ID: {job_3.job_id}")
Job ID: df911d83-9df7-44a1-bfad-5d66e08676c3
# Monitor the job status
job_3.status()
'RUNNING: WAITING_FOR_QPU'

Крок 3: отримайте та візуалізуйте результати​

Отримайте та візуалізуйте результати.

result = job_3.result()
solution = result["solutions"][0]

# Map each node to its assigned color group
node_group = {}
for i in G.nodes:
for c in range(k):
if solution[f"x{i},{c}"] == 1:
node_group[i] = c

print(f"Feasible: {result['feasible']}")
print(f"Violations: {int(result['objective_value'])}")

# Visualize the partition
colors = ["tab:blue", "tab:orange", "tab:green"]
node_colors = [colors[node_group[i]] for i in G.nodes()]
nx.draw(G, nx.kamada_kawai_layout(G), node_color=node_colors, node_size=200)
Feasible: True
Violations: 4

Output of the previous code cell

Журнал змін​

[0.4.0] - 2026-09-22​

Зміни, що порушують сумісність

  • Вхідний параметр model перейменовано на problem.
  • Вихідне поле obj_value перейменовано на objective_value.
  • Опцію postprocessing замінено на postprocessing_level, яка приймає ціле число в діапазоні [0, 3] замість рядка. Попередні значення відповідають так: "off" -> 0, "weak" -> 1, "medium" -> 2 і "strong" -> 3, а значення за замовчуванням не змінилося і дорівнює 3.
  • Змінено структуру metadata.circuit_metrics. Тепер вона повертає num_qubits, gate_count, depth, two_qubit_gate_count, two_qubit_gate_depth та operations окремо для before_transpilation і after_transpilation замість одного плоского словника усереднених кількостей гейтів. Поле має значення None, коли задачу розв'язано під час попередньої обробки й жодну схему не було виконано (код помилки 4712).

Можливості

  • Додано опцію seed_transpiler, щоб синтез і маршрутизація схеми були відтворюваними між запусками.
  • Додано опцію job_tags, щоб прикріплювати власні теги до кожного завдання Qiskit Runtime, яке надсилає функція.
  • Додано вихідне поле solution_bitstrings, яке повертає ті самі розв'язки, що й solutions, у вигляді бітових рядків.
  • Додано metadata.solver_info.variable_mapping, яке зіставляє ім'я кожної змінної з позицією її символу в елементах solution_bitstrings.

Документація

  • Задокументовано, що неперервні (дійсні) змінні не підтримуються, а цілочисельні змінні потребують явних меж. Такі моделі завершуються помилкою з кодом 4710.

Отримати підтримку​

Якщо у вас виникли запитання чи проблеми, звертайтеся на support@aqarios.com, зазначивши ID завдання.

Подальші кроки​

Рекомендації

Джерела​

  1. Bucher et al. (2026), Constrained Quantum Optimization via Iterative Warm-Start XY-Mixers 10.1088/1367-2630/ae8ea2