Constrained Quantum Optimizer - O funcție Qiskit de la Aqarios
Consultă referința API
Qiskit Functions sunt o caracteristică experimentală disponibilă doar utilizatorilor IBM Quantum® cu plan Premium, plan Flex și plan On-Prem (prin API-ul IBM Quantum Platform). Acestea au statut de versiune preliminară (preview) și pot fi modificate.
Prezentare generală
Cu Constrained Quantum Optimizer de la Aqarios, poți rezolva probleme de optimizare binară cu constrângeri pe hardware cuantic IBM® fără reformularea manuală a problemei și fără maparea circuitului. Este suficient să furnizezi o problemă ca fișier LP, fișier MPS sau ca Luna Model. Funcția se ocupă automat de reformulare, sinteza circuitului, transpilare și execuția pe hardware. Solverul utilizează warm-starting iterativ [1] al algoritmului FlexQAOA, o extensie a algoritmului QAOA (Quantum Approximate Optimization Algorithm) care tratează nativ constrângerile.
Optimizatorul vizează probleme binare cu constrângeri. În special, constrângerile one-hot și constrângerile set-packing pot fi impuse nativ utilizând XY-mixers. Alte tipuri de constrângeri sunt reformulate automat ca termeni de penalizare.
Funcția rezolvă doar probleme discrete. Fiecare variabilă de decizie trebuie să fie binară sau întreagă, cu o limită inferioară și una superioară explicite, astfel încât să poată fi codificată în qubiți. Variabilele continue (cu valori reale) nu sunt acceptate: un model care le conține este respins cu codul de eroare 4710.
Descriere
Performanța poate depinde atât de instanța problemei, cât și de etapele de procesare ulterioare. În unele cazuri, eșantioanele clasice și cele generate cuantic pot atinge o calitate finală similară a soluției după o post-procesare echivalentă. Evaluarea ar trebui, prin urmare, să ia în considerare întregul flux de optimizare.
Constrained Quantum Optimizer implementează Iterative warm-start XY-mixer QAOA (IWS-QAOA) [1]. Algoritmul rulează circuite QAOA cu unghi fix pe hardware cuantic și actualizează probabilitățile inițiale de warm-start ale fiecărui circuit utilizând rezultatele măsurătorilor din iterația anterioară. Nu este necesară antrenarea parametrilor variaționali; în schimb, se alege o parametrizare cu rampă liniară fixă.
Utilizând XY-mixers pentru a impune constrângeri one-hot, poți îmbunătăți drastic calitatea soluțiilor pentru problemele cu constrângeri, deoarece spațiul de căutare este redus practic la un subspațiu fezabil mai mic — iar peisajul de optimizare nu capătă complexitate suplimentară din cauza termenilor de penalizare.
Flux de lucru
Fluxul de lucru al funcției este descris mai jos:
-
Preprocesare: Înainte de sinteza circuitului, optimizatorul analizează structura constrângerilor problemei de intrare:
-
Preprocesarea grafului: Atunci când este aplicabil problemei, aceasta este analizată ca un graf, în care muchiile determină relația dintre variabile. Această analiză a grafului permite două îmbunătățiri de preprocesare a problemei. În primul rând, constrângerile individuale pot fi agregate într-o singură constrângere mare prin combinarea de clici (clique merging), astfel încât să fie reprezentate printr-un singur XY-mixer. În al doilea rând, variabilele care au un singur vecin pot fi fixate în mod determinist, reducând dimensiunea și complexitatea problemei.
-
Rezolvarea constrângerilor: Preprocesorul tratează fiecare constrângere separat: dacă constrângerea este de tip one-hot, aceasta poate fi impusă prin XY-mixers. Dacă este o constrângere de tip set-packing, aceasta este mai întâi transformată într-o constrângere one-hot. Constrângerile de egalitate sunt tratate prin penalizări pătratice, iar cele de inegalitate prin penalizare dezechilibrată.
-
Derivarea penalizării: Constrângerile care nu pot fi exprimate ca constrângeri de egalitate one-hot sunt convertite în termeni de penalizare. Optimizatorul derivă automat intensitatea penalizării din structura problemei.
-
-
Warm-starting iterativ: Optimizatorul rulează mai multe lanțuri de warm-start paralele. Fiecare lanț deține o distribuție de probabilitate peste atribuirile variabilelor, care este utilizată ca probabilitate de pornire a circuitului QAOA (starea de warm-start). La fiecare iterație, un lanț eșantionează din circuitul cuantic, aplică post-procesare clasică și își actualizează distribuția pe baza apariției eșantioanelor. De-a lungul iterațiilor, aceasta concentrează căutarea pe soluții de înaltă calitate fără o buclă de optimizare variațională.
Numărul de lanțuri (num_parallel), bugetul total de shot-uri per lanț (total_shots) și numărul de repetiții QAOA (reps) sunt principalele controale pentru a echilibra calitatea soluției cu timpul de execuție.
Benchmark-uri
Benchmark-urile de mai jos arată că funcția Qiskit Constrained Quantum Optimizer este capabilă să găsească soluții fezabile, de înaltă calitate, pentru probleme de optimizare cu constrângeri cu mult peste 100 de variabile binare. Acuratețea este raportul dintre valoarea obiectiv găsită și optimul cunoscut. Timpul de execuție este timpul real (wall-clock) de la invocarea funcției până la livrarea rezultatului. Utilizarea QPU este timpul de calcul cuantic facturabil.
Au fost examinate două probleme: problema Maximum Independent Set (MIS) și Max--Cut, care este o extensie a binecunoscutei probleme MaxCut la mai mult de două categorii. Max--Cut este, de asemenea, varianta de optimizare echivalentă a problemei de decizie a colorării grafurilor (atunci când toate muchiile sunt tăiate, graful este -colorabil).
| Problemă | Variabile | Constrângeri | Qubiți | Acuratețe | Fezabilitate | Timp total de execuție (s) | Utilizare QPU (s) | Total shot-uri |
|---|---|---|---|---|---|---|---|---|
| MIS es60fst02 | 186 | 280 | 124 | 100.0% | True | 940.2 | 147.0 | 25.0k |
| MIS sloane_2dc_128 | 128 | 5173 | 74 | 100.0% | True | 347.6 | 106.0 | 12.5k |
| Max-3-Cut Karate Club | 99 | 33 | 99 | 98.7% | True | 279.5 | 166.0 | 25.0k |
| Max-4-Cut Karate Club | 132 | 33 | 132 | 100.0% | True | 258.3 | 200.0 | 25.0k |
Note privind benchmark-urile
-
Rezultatele de mai sus au fost obținute pe procesorul Heron r2
ibm_marrakeshcu opțiunile implicite șiuse_sessionactivat. Pentru instanțasloane_2dc_128, a fost utilizattotal_shots=12500. -
Numărul redus de qubiți pentru instanțele MIS (74 și 124 față de 128 și 186 de variabile) reflectă fixarea variabilelor în etapa de preprocesare.
-
Instanțele problemei pentru MIS sunt preluate din Quantum Optimization Benchmarking Library. - Instanța pentru problema Max--Cut este graful Zachary Karate Club, care are un număr cromatic de 5.
Primii pași
Acest ghid demonstrează utilizarea de bază a Constrained Quantum Optimizer, arătând cum se încarcă funcția și cum se execută probleme simple. Pentru un tutorial mai amplu, consultă Find the Maximum Independent Set with the Aqarios Constrained Quantum Optimizer.
Autentifică-te cu cheia API IBM Quantum și CRN-ul instanței, apoi încarcă funcția din catalog.
Codul următor presupune că ai salvat deja acreditările. Pentru a le configura, urmează instrucțiunile din Salvează acreditările contului tău IBM Cloud.
# 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")
Exemplul 1: O problemă simplă cu constrângeri
Primul exemplu arată cum se utilizează funcția cu fișiere LP, o specificație obișnuită pentru probleme de optimizare utilizată în cercetarea operațională. Vei formula următoarea problemă de optimizare arbitrară cu cinci variabile binare supuse la două constrângeri:
1. Formulează problema
Exprimă direct expresia matematică în următorul format de șir 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
"""
Reține că [ ... ] / 2 este o notație necesară pentru obiectivele pătratice conform standardului LP.
2. Rulează optimizatorul
Rezolvă problema cu optimizatorul.
# 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. Preia rezultatul
Soluția, care mapează numele variabilelor la atribuirile asociate, este furnizată de rezultat.
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}}}}
Câmpul solutions din dicționarul returnat conține toate cele mai bune soluții degenerate găsite, sub formă de dicționare care asociază fiecare nume de variabilă cu valoarea sa atribuită. Aceleași soluții sunt returnate și ca șiruri de biți în solution_bitstrings; metadata.solver_info.variable_mapping îți spune ce poziție de caracter dintr-un șir de biți aparține cărei variabile. Pe lângă datele soluției, sunt furnizate objective_value, un indicator feasible și metadata suplimentare.
Exemplul 2: Maximum Independent Set
Problema Maximum Independent Set (MIS) cere cel mai mare subset de vârfuri dintr-un graf astfel încât niciun vârf din subset să nu fie conectat prin muchie cu un alt vârf din subset. Acest exemplu rezolvă MIS pe un graf regulat cu 12 noduri. Pentru mai multe informații despre problemă și un exemplu mai amplu, consultă tutorialul.
Problema este construită cu qiskit-addon-opt-mapper. Instalează pachetele necesare dacă este cazul:
# %pip install networkx qiskit-addon-opt-mapper
Pasul 1: Definește problema
Construiește un graf regulat aleatoriu de gradul 3 și creează problema de optimizare MIS. Fiecare nod al grafului devine o variabilă binară, iar fiecare muchie introduce o constrângere care asigură că cel mult unul dintre capete este selectat.
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
Pasul 2: Rulează optimizatorul
Rezolvă problema cu optimizatorul.
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'
Pasul 3: Preia și interpretează rezultatele
În cele din urmă, preluăm soluția și verificăm corectitudinea acesteia.
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: []
Exemplul 3: Colorarea grafului cu 3 culori (Max-3-Cut)
Problema Max--Cut împarte vârfurile unui graf în grupuri pentru a maximiza numărul de muchii ale căror capete aparțin unor grupuri diferite. Pentru , aceasta este echivalentă cu găsirea unei colorări cu 3 culori care maximizează muchiile dintre culori diferite.
Formal, se atribuie fiecărui nod unul dintre cele grupuri, folosind variabile binare pentru culoarea . Constrângerea one-hot pentru fiecare nod impune o atribuire unică. Obiectivul maximizează muchiile dintre grupuri diferite:
Constrângerile one-hot sunt ideale pentru XY-mixers, pe care optimizatorul le gestionează nativ.
Acest exemplu utilizează graful Zachary Karate Club (34 de noduri, 78 de muchii) și construiește modelul cu Luna Model. Instalează pachetele necesare dacă este cazul:
# %pip install networkx matplotlib luna-model
Pasul 1: Definește problema
Mai întâi, generează variabilele binare cu pachetul luna-model. Apoi, definește obiectivul și adaugă constrângerile la 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()
Pasul 2: Rulează optimizatorul
Rezolvă problema cu optimizatorul.
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'
Pasul 3: Preia și vizualizează rezultatele
Preia și vizualizează rezultatele.
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

Jurnal de modificări
[0.4.0] - 2026-09-22
Modificări incompatibile
- Parametrul de intrare
modela fost redenumit înproblem. - Câmpul de ieșire
obj_valuea fost redenumit înobjective_value. - Opțiunea
postprocessinga fost înlocuită cupostprocessing_level, care primește un număr întreg în intervalul[0, 3]în loc de un șir de caractere. Valorile anterioare se asociază astfel:"off"->0,"weak"->1,"medium"->2și"strong"->3, iar valoarea implicită rămâne neschimbată la3. metadata.circuit_metricsa fost restructurat. Acum raporteazănum_qubits,gate_count,depth,two_qubit_gate_count,two_qubit_gate_depthșioperationsseparat pentrubefore_transpilationșiafter_transpilation, în loc de un singur dicționar plat cu numere medii de porți. Câmpul esteNonecând problema a fost rezolvată în timpul preprocesării și nu a fost rulat niciun circuit (codul de eroare4712).
Funcționalități
- A fost adăugată opțiunea
seed_transpilerpentru a face sinteza și rutarea circuitului reproductibile între rulări. - A fost adăugată opțiunea
job_tagspentru a atașa propriile etichete fiecărui job Qiskit Runtime trimis de funcție. - A fost adăugat câmpul de ieșire
solution_bitstrings, care returnează aceleași soluții casolutions, sub formă de șiruri de biți. - A fost adăugat
metadata.solver_info.variable_mapping, care asociază fiecare nume de variabilă cu poziția sa de caracter în intrările dinsolution_bitstrings.
Documentație
- S-a documentat că variabilele continue (cu valori reale) nu sunt acceptate și că variabilele întregi necesită limite explicite. Astfel de modele eșuează cu codul de eroare
4710.
Obține asistență
Pentru întrebări sau probleme, contactează support@aqarios.com menționând ID-ul jobului tău.
Pași următori
- Solicită acces la Constrained Quantum Optimizer de la Aqarios.
- Vizitează referința API pentru documentația completă a parametrilor și a rezultatelor.
- Încearcă tutorialul Find the Maximum Independent Set with the Aqarios Constrained Quantum Optimizer pentru o analiză detaliată a unei instanțe reale de benchmark QOBLIB.
- Consultă publicația Constrained Quantum Optimization via Iterative Warm-Start XY-Mixers.
Referințe
- Bucher et al. (2026), Constrained Quantum Optimization via Iterative Warm-Start XY-Mixers 10.1088/1367-2630/ae8ea2