Przejdź do głównej treści

Iskay Quantum Optimizer – funkcja Qiskit od Kipu Quantum

Uwaga
  • Funkcje Qiskit to funkcja eksperymentalna dostępna wyłącznie dla użytkowników planów IBM Quantum® Premium Plan, Flex Plan i On-Prem (przez IBM Quantum Platform API). Mają one status wersji przedpremierowej i mogą ulec zmianie.

Przegląd

Dzięki Iskay Quantum Optimizer od Kipu Quantum możesz rozwiązywać złożone problemy optymalizacyjne przy użyciu komputerów kwantowych IBM®. Ten solver wykorzystuje najnowocześniejszy algorytm bf-DCQO firmy Kipu, który wymaga jedynie funkcji celu jako danych wejściowych, aby automatycznie dostarczać rozwiązania problemów. Radzi sobie z problemami optymalizacyjnymi obejmującymi do 156 Qubitów, umożliwiając wykorzystanie wszystkich Qubitów urządzeń kwantowych IBM. Optimizer stosuje odwzorowanie 1-do-1 między zmiennymi klasycznymi a Qubitami, co pozwala rozwiązywać problemy optymalizacyjne z maksymalnie 156 zmiennymi binarnymi.

Optimizer umożliwia rozwiązywanie binarnych problemów optymalizacyjnych bez ograniczeń. Oprócz powszechnie stosowanej formulacji QUBO (Quadratic Unconstrained Binary Optimization) obsługuje również problemy optymalizacyjne wyższego rzędu (HUBO). Solver wykorzystuje niewa­riacyjny algorytm kwantowy, wykonując większość obliczeń na urządzeniach kwantowych.

Poniżej znajdziesz więcej szczegółów na temat zastosowanego algorytmu oraz krótki przewodnik po sposobie korzystania z funkcji, a także wyniki testów porównawczych dla różnych instancji problemów o różnych rozmiarach i złożonościach.

Opis

Optimizer to gotowa do użycia implementacja najnowocześniejszych algorytmów optymalizacji kwantowej. Rozwiązuje problemy optymalizacyjne, uruchamiając wysoce skompresowane Circuit na sprzęcie kwantowym. Kompresja ta jest osiągana poprzez wprowadzenie terminów kontradiabatycznych do bazowej ewolucji czasowej układu kwantowego. Algorytm wykonuje kilka iteracji uruchomień sprzętowych, aby uzyskać końcowe rozwiązania, i łączy je z przetwarzaniem końcowym. Kroki te są płynnie zintegrowane z przepływem pracy Optimizera i wykonywane automatycznie.

Jak działa Quantum Optimizer?

Ta sekcja przedstawia podstawy zaimplementowanego algorytmu bf-DCQO. Wprowadzenie do algorytmu można również znaleźć na kanale YouTube Qiskit.

Algorytm opiera się na ewolucji czasowej układu kwantowego, który zmienia się w czasie, przy czym rozwiązanie problemu jest zakodowane w stanie podstawowym układu kwantowego na końcu ewolucji. Zgodnie z twierdzeniem adiabatycznym, ta ewolucja musi przebiegać powoli, aby układ pozostawał w swoim stanie podstawowym. Digitalizacja tej ewolucji stanowi podstawę cyfrowego kwantowego obliczania adiabatycznego (DQA) i niesławnego algorytmu QAOA. Jednak wymagana powolna ewolucja nie jest wykonalna dla coraz większych rozmiarów problemów, ponieważ skutkuje rosnącą głębokością Circuit. Stosując protokoły kontradiabatyczne, możesz tłumić niechciane wzbudzenia pojawiające się w krótkich czasach ewolucji, pozostając jednocześnie w stanie podstawowym. Tutaj digitalizacja tego krótszego czasu ewolucji skutkuje Circuit o mniejszej głębokości i mniejszej liczbie bramek splątujących.

Circuit algorytmów bf-DCQO zazwyczaj wykorzystują do dziesięciu razy mniej bramek splątujących niż DQA oraz od trzech do czterech razy mniej bramek splątujących niż standardowe implementacje QAOA. Ze względu na mniejszą liczbę Gate, podczas wykonywania Circuit na sprzęcie pojawia się mniej błędów. Dlatego optimizer nie wymaga stosowania technik takich jak tłumienie błędów czy łagodzenie błędów. Ich implementacja w przyszłych wersjach może jeszcze bardziej poprawić jakość rozwiązań.

Choć algorytm bf-DCQO korzysta z iteracji, jest niewa­riacyjny. Po każdej iteracji algorytmu mierzona jest dystrybucja stanów. Uzyskana dystrybucja służy do obliczenia tzw. pola biasu. Pole biasu umożliwia rozpoczęcie następnej iteracji ze stanu energetycznego bliskiego poprzednio znalezionemu rozwiązaniu. W ten sposób algorytm z każdą iteracją przesuwa się ku rozwiązaniom o niższej energii. Zazwyczaj około dziesięciu iteracji wystarczy, aby zbiec do rozwiązania, co łącznie wymaga znacznie mniejszej liczby iteracji niż algorytmy wariacyjne, gdzie wynosi ona rzędu około 100 iteracji.

Optimizer łączy algorytm bf-DCQO z klasycznym przetwarzaniem końcowym. Po zmierzeniu dystrybucji stanów wykonywane jest lokalne przeszukiwanie. W trakcie lokalnego przeszukiwania bity zmierzonego rozwiązania są losowo odwracane. Po odwróceniu oceniana jest energia nowego ciągu bitów. Jeśli energia jest niższa, ciąg bitów jest zachowywany jako nowe rozwiązanie. Lokalne przeszukiwanie skaluje się jedynie liniowo z liczbą Qubitów, jest więc obliczeniowo tanie. Ponieważ przetwarzanie końcowe koryguje lokalne odwrócenia bitów, kompensuje błędy odwrócenia bitów, które często są wynikiem niedoskonałości sprzętowych i błędów odczytu.

Przepływ pracy

Poniżej przedstawiono schemat przepływu pracy Quantum Optimizera.

Workflow

Korzystając z Quantum Optimizera, rozwiązanie problemu optymalizacyjnego na sprzęcie kwantowym można sprowadzić do:

  • Sformułowania funkcji celu problemu
  • Uzyskania dostępu do Optimizera przez Qiskit Functions
  • Uruchomienia Optimizera i zebrania wyników

Testy porównawcze

Poniższe wskaźniki testów porównawczych pokazują, że Optimizer skutecznie rozwiązuje problemy obejmujące do 156 Qubitów i oferują ogólny przegląd dokładności oraz skalowalności optimizera w różnych typach problemów. Zwróć uwagę, że rzeczywiste wskaźniki wydajności mogą się różnić w zależności od specyficznych właściwości problemu, takich jak liczba zmiennych, gęstość i lokalność terminów w funkcji celu oraz rząd wielomianu.

Poniższa tabela zawiera współczynnik aproksymacji (AR), który jest zdefiniowany następująco:

AR=CCmaxCminCmax,AR = \frac{C^{*} - C_\textrm{max}}{C_{\textrm{min}} - C_{\textrm{max}}},

gdzie CC to funkcja celu, CminC_{\textrm{min}}, CmaxC_{\textrm{max}} to odpowiednio jej wartość minimalna i maksymalna, a CC^{*} to koszt najlepszego znalezionego rozwiązania. Zatem AR=100% oznacza, że uzyskano stan podstawowy problemu.

PrzykładLiczba QubitówWspółczynnik aproksymacjiŁączny czas (s)Czas użycia Runtime (s)Łączna liczba pomiarówLiczba iteracji
Unweighted MaxCut28100%1803030k5
Unweighted MaxCut30100%1803030k5
Unweighted MaxCut32100%1803030k5
Unweighted MaxCut80100%4806090k9
Unweighted MaxCut100100%3306060k6
Unweighted MaxCut120100%3706060k6
HUBO 1156100%60070100k10
HUBO 2156100%60070100k10
  • Instancje MaxCut z 28, 30 i 32 Qubitami były uruchamiane na ibm_sherbrooke. Instancje z 80, 100 i 120 Qubitami były uruchamiane na procesorze Heron r2.
  • Instancje HUBO były również uruchamiane na procesorze Heron r2.

Wszystkie instancje testów porównawczych są dostępne na GitHubie (zob. instancje testów Kipu). Przykład uruchomienia tych instancji można znaleźć w Przykładzie 3: Instancje testów porównawczych.

Wejście i wyjście

Wejście

W poniższej tabeli znajdziesz wszystkie parametry wejściowe akceptowane przez Quantum Optimizer. Następna sekcja Opcje zawiera więcej szczegółów na temat dostępnych options.

NazwaTypOpisWymaganeDomyślniePrzykład
problemDict[str, float]Współczynniki problemu optymalizacyjnego sformułowanego w formacie QUBO/HUBO lub spinowym. Więcej informacji na temat specyfikacji problemu znajdziesz w sekcji Akceptowane formaty problemuTakN/A{"()": -21.0, "(0, 4)": 0.5,"(0, 2)": 0.5,"(0, 1)": 0.5,"(1, 3)": 0.5}
problem_typestrOkreśl, czy współczynniki problemu są w formacie binarnym (QUBO/HUBO), czy spinowym. Dwie możliwości to "spin" lub "binary"TakN/A"spin"
backend_namestrNazwa Backend, do którego kierowane jest zapytanieTakN/A"ibm_fez"
optionsDict[str, Any]Opcje obsługi zgłoszenia sprzętowego, takie jak liczba pomiarów. Więcej szczegółów na temat konfiguracji opcji znajdziesz w sekcji OpcjeNieDomyślne wartości konfiguracji opcji znajdziesz w sekcji Opcje{"shots": 5000, "num_iterations": 3, "use_session": True, "seed_transpiler": 42}

Akceptowane formaty problemu

Argumenty problem i problem_type kodują problem optymalizacyjny postaci

min(x1,x2,,xn)DC(x1,x2,,xn)\begin{align} \min_{(x_1, x_2, \ldots, x_n) \in D} C(x_1, x_2, \ldots, x_n) \nonumber \end{align}

gdzie

C(x1,...,xn)=a+ibixi+i,jci,jxixj+...+k1,...,kmgk1,...,kmxk1...xkmC(x_1, ... , x_n) = a + \sum_{i} b_i x_i + \sum_{i, j} c_{i, j} x_i x_j + ... + \sum_{k_1, ..., k_m} g_{k_1, ..., k_m} x_{k_1} ... x_{k_m}
  • Wybierając problem_type = "binary", określasz, że funkcja kosztu jest w formacie binary, co oznacza, że D={0,1}nD = \{0, 1\}^{n}, tzn. funkcja kosztu jest zapisana w formulacji QUBO/HUBO.
  • Natomiast wybierając problem_type = "spin", funkcja kosztu jest zapisana w formulacji Isinga, gdzie D={1,1}nD = \{-1, 1\}^{n}.

Współczynniki problemu należy zakodować w słowniku w następujący sposób:

{"()":a,"(i,)":bi,"(i, j)":ci,j,"(k1,...,km)":gk1,...,km,}\begin{align} \nonumber &\texttt{\{} \\ \nonumber &\texttt{"()"}&: \quad &a, \\ \nonumber &\texttt{"(i,)"}&: \quad &b_i, \\ \nonumber &\texttt{"(i, j)"}&: \quad &c_{i, j}, \\ \nonumber &\quad \vdots \\ \nonumber &\texttt{"(} k_1, ..., k_m \texttt{)"} &: \quad &g_{k_1, ..., k_m}, \\ \nonumber &\texttt{\}} \end{align}
  • Zwróć uwagę, że klucze słownika muszą być ciągami znaków zawierającymi poprawną krotkę niepowtarzających się liczb całkowitych.

Opcje

Iskay udostępnia możliwości dokładnego dostrajania za pomocą opcjonalnych parametrów. Choć domyślne wartości sprawdzają się w większości problemów, możesz dostosować zachowanie do konkretnych wymagań:

ParametrTypDomyślnieOpis
shotsint10000Liczba pomiarów kwantowych na iterację (wyższa wartość = większa dokładność)
num_iterationsint10Liczba iteracji algorytmu (więcej iteracji może poprawić jakość rozwiązania)
use_sessionboolTrueUżyj sesji IBM w celu skrócenia czasu oczekiwania w kolejce
seed_transpilerintNoneUstaw, aby zapewnić powtarzalną kompilację Circuit kwantowego
direct_qubit_mappingboolFalseMapuj wirtualne Qubit bezpośrednio na fizyczne Qubit
job_tagsList[str]NoneNiestandardowe tagi do śledzenia zadań
preprocessing_levelint0Intensywność wstępnego przetwarzania problemu (0–3) — szczegóły poniżej
postprocessing_levelint2Poziom dopracowania rozwiązania (0–2) — szczegóły poniżej
transpilation_levelint0Liczba prób optymalizacji Transpiler (0–5) — szczegóły poniżej
transpile_onlyboolFalseAnalizuj optymalizację Circuit bez uruchamiania pełnego wykonania

Poziomy wstępnego przetwarzania (0–3): Szczególnie istotne w przypadku większych problemów, które aktualnie nie mieszczą się w czasie dekoherencji sprzętu. Wyższe poziomy wstępnego przetwarzania osiągają mniejsze głębokości Circuit poprzez aproksymacje w transpilacji problemu:

  • Poziom 0: Dokładny, dłuższe Circuit
  • Poziom 1: Dobry balans między dokładnością a aproksymacją — pomija tylko Gate z kątami w najniższym 10. percentylu
  • Poziom 2: Nieco wyższa aproksymacja — pomija Gate z kątami w najniższym 20. percentylu i używa approximation_degree=0.95 podczas transpilacji
  • Poziom 3: Maksymalny poziom aproksymacji — pomija Gate w najniższym 30. percentylu i używa approximation_degree=0.90 podczas transpilacji

Poziomy transpilacji (0–5): Kontrolują zaawansowane próby optymalizacji Transpiler przy kompilacji Circuit kwantowego. Może to zwiększyć narzut klasyczny, a w niektórych przypadkach może nie zmieniać głębokości Circuit. Wartość domyślna 2 na ogół daje najmniejszy Circuit i jest relatywnie szybka.

  • Poziom 0: Optymalizacja rozłożonego Circuit DCQO (układ, routing, harmonogramowanie)
  • Poziom 1: Optymalizacja PauliEvolutionGate, a następnie rozłożonego Circuit DCQO (max_trials=10)
  • Poziom 2: Optymalizacja PauliEvolutionGate, a następnie rozłożonego Circuit DCQO (max_trials=15)
  • Poziom 3: Optymalizacja PauliEvolutionGate, a następnie rozłożonego Circuit DCQO (max_trials=20)
  • Poziom 4: Optymalizacja PauliEvolutionGate, a następnie rozłożonego Circuit DCQO (max_trials=25)
  • Poziom 5: Optymalizacja PauliEvolutionGate, a następnie rozłożonego Circuit DCQO (max_trials=50)

Poziomy postprocessingu (0–2): Kontrolują ilość klasycznej optymalizacji kompensującej błędy odwrócenia bitów, z różną liczbą zachłannych przebiegów lokalnego przeszukiwania:

  • Poziom 0: 1 przebieg
  • Poziom 1: 2 przebiegi
  • Poziom 2: 3 przebiegi

Tryb tylko transpilacji: Dostępny teraz dla użytkowników, którzy chcą analizować optymalizację Circuit bez uruchamiania pełnego wykonania algorytmu kwantowego.

Przykład niestandardowej konfiguracji: Oto jak możesz skonfigurować Iskay z różnymi ustawieniami:

# Added by doQumentation — required packages for this notebook
!pip install -q PyGithub networkx qiskit-ibm-catalog
custom_options = {
"shots": 15_000, # Higher shot count for better statistics
"num_iterations": 12, # More iterations for solution refinement
"preprocessing_level": 1, # Light preprocessing for problem simplification
"postprocessing_level": 2, # Maximum postprocessing for solution quality
"transpilation_level": 3, # Using higher transpilation level for circuit optimization
"seed_transpiler": 42, # Fixed seed for reproducible results
"job_tags": ["custom_config"], # Custom tracking tags
}

Optymalizacja ziarna: Pamiętaj, że seed_transpiler jest domyślnie ustawiony na None. Umożliwia to automatyczny proces optymalizacji Transpiler. Gdy wartość wynosi None, system rozpocznie próbę z wieloma ziarnami i wybierze to, które daje najlepszą głębokość Circuit, w pełni wykorzystując parametr max_trials dla każdego poziomu transpilacji.

Wydajność poziomów transpilacji: Zwiększanie liczby max_trials przez ustawianie wyższych wartości transpilation_level nieuchronnie wydłuży czas transpilacji, ale nie zawsze zmieni ostateczny Circuit — zależy to w dużej mierze od konkretnej struktury i złożoności Circuit. Jednak w przypadku niektórych Circuit/problemów różnica między 10 próbami (poziom 1) a 50 próbami (poziom 5) może być dramatyczna, dlatego eksploracja tych parametrów może być kluczem do skutecznego znalezienia rozwiązania.

Output

NameTypeDescriptionExample
resultDict[str, Any]Rozwiązanie i metadane. Struktura zależy od opcji transpile_only.Zobacz „Zawartość słownika wyników" poniżej

Zawartość słownika wyników

Struktura słownika wyników zależy od trybu wykonania:

FieldTypeModeDescriptionExample
solutionDict[str, int]StandardPosortowane zmapowane rozwiązanie, w którym klucze są indeksami zmiennych (jako ciągi znaków) posortowanymi numerycznie, a wartości są odpowiadającymi wartościami zmiennych (1/-1 dla problemów spinowych, 1/0 dla problemów binarnych).{'0': -1, '1': -1, '2': -1, '3': 1, '4': 1}
solution_infoDict[str, Any]StandardSzczegółowe informacje o rozwiązaniu (szczegóły poniżej){'bitstring': '11100', 'cost': -13.8, 'seed_transpiler': 42, 'mapping': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}}
prob_typestrStandardTyp problemu optymalizacyjnego ('spin' lub 'binary')'spin'
transpilation_infoDict[str, Any]Tylko transpilacjaAnaliza Circuit i szczegóły transpilacji (szczegóły poniżej){'best_seed': 42, 'transpilation_time_seconds': 50.06, 'transpiled_circuit': {'depth': 576, 'gate_count': 4177, 'num_qubits': 156, 'width': 176, 'operations': {'sx': 1325, 'rx': 891, 'cz': 783, 'rz': 650, 'rzz': 466, 'x': 42, 'measure': 20}}}

Standardowe wykonanie

Gdy opcjonalny parametr transpile_only=False:

Słownik solution_info:

  • "bitstring" (str): Surowa reprezentacja bitstring rozwiązania.
  • "cost" (float): Wartość kosztu/energii powiązana z rozwiązaniem.
  • "seed_transpiler" (int): Losowe ziarno użyte przez Transpiler, który wyprodukował ten wynik.
  • "mapping" (Dict[int, int]): Oryginalne mapowanie Qubit na zmienne użyte w obliczeniach.
  • "qpu_time" (float, opcjonalnie): Czas wykonania QPU w sekundach.

Uwagi dotyczące mapowania zmiennych:

  • Słownik solution jest uzyskiwany z bitstring rozwiązania przy użyciu obiektu mapping do indeksowania zmiennych.
  • Gdy problem_type=spin, stosujemy przypisanie 11,011 \rightarrow -1, \quad 0 \rightarrow 1.
  • Klucze w słowniku rozwiązania są indeksami zmiennych posortowanymi numerycznie jako ciągi znaków.

Analiza transpilacji

Gdy opcjonalny parametr transpile_only=True:

Słownik transpilation_info:

  • "best_seed" (int): Optymalne ziarno znalezione dla transpilacji
  • "transpilation_time_seconds" (float): Czas poświęcony na proces transpilacji
  • "transpiled_circuit" (Dict): Analiza Circuit zawierająca:
    • "depth" (int): Głębokość Circuit (liczba warstw)
    • "gate_count" (int): Całkowita liczba Gate w Circuit
    • "num_qubits" (int): Liczba użytych Qubit
    • "width" (int): Szerokość Circuit
    • "operations" (Dict[str, int]): Liczba każdego użytego typu Gate

Użycie trybu tylko transpilacji:

  • Dostępny dla użytkowników, którzy chcą analizować optymalizację Circuit bez uruchamiania pełnego wykonania algorytmu kwantowego.

Pierwsze kroki

W tej dokumentacji przeprowadzimy cię przez kolejne etapy korzystania z Iskay Quantum Optimizer. Po drodze pokażemy, jak załadować funkcję z katalogu i jak przekształcić swój problem na prawidłowe dane wejściowe, demonstrując jednocześnie eksperymentowanie z różnymi opcjonalnymi parametrami.

Bardziej szczegółowy przykład znajdziesz w samouczku Rozwiąż problem podziału rynku z Iskay Quantum Optimizer od Kipu Quantum, w którym przechodzimy przez cały proces korzystania z Iskay Solver w celu rozwiązania problemu Market Split — rzeczywistego wyzwania alokacji zasobów, gdzie rynki muszą być podzielone na zrównoważone regiony sprzedaży spełniające dokładne cele popytu.

Uwierzytelnij się za pomocą klucza API, który znajdziesz na pulpicie nawigacyjnym IBM Quantum Platform, a następnie wybierz Qiskit Function w następujący sposób:

# ruff: noqa: F821
uwaga

Poniższy kod zakłada, że zapisałeś już swoje dane uwierzytelniające. Jeśli tego nie zrobiłeś, postępuj zgodnie z instrukcjami w sekcji zapisz swoje konto IBM Cloud, aby uwierzytelnić się za pomocą klucza API.

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(
channel="ibm_quantum_platform",
instance="INSTANCE_CRN",
token="YOUR_API_KEY", # Use the 44-character API_KEY you created and saved from the IBM Quantum Platform Home dashboard
)

# Access Function
optimizer = catalog.load("kipu-quantum/iskay-quantum-optimizer")

Przykład 1: Prosta funkcja kosztów

Rozważmy funkcję kosztów w sformułowaniu spinowym:

C(x0,x1,x2,x3,x4)=1+1.5x0+2x1+1.3x2+2.5x0x3+3.5x1x4+4x0x1x2C(x_0, x_1, x_2, x_3, x_4) = 1 + 1.5x_0 + 2x_1 + 1.3x_2 + 2.5x_0x_3 + 3.5x_1x_4 + 4x_0x_1x_2

gdzie (x0,...,x4){1,1}5(x_0, ..., x_4) \in \{-1, 1\}^5.

Rozwiązaniem tej prostej funkcji kosztów jest

(x0,x1,x2,x3,x4)=(1,1,1,1,1)(x_0, x_1, x_2, x_3, x_4) = (-1, -1, -1, 1, 1)

z wartością minimalną C=6C^{*} = -6

1. Utwórz funkcję celu

Zaczynamy od utworzenia słownika ze współczynnikami funkcji celu:

objective_func = {
"()": 1,
"(0,)": 1.5,
"(1,)": 2,
"(2,)": 1.3,
"(0, 3)": 2.5,
"(1, 4)": 3.5,
"(0, 1, 2)": 4,
}

2. Uruchom Optimizer

Rozwiązujemy problem, uruchamiając optimizer. Ponieważ (x0,...,x4){1,1}5(x_0, ..., x_4) \in \{-1, 1\}^5, musimy ustawić problem_type=spin.

# Setup options to run the optimizer
options = {"shots": 5000, "num_iterations": 5, "use_session": True}

arguments = {
"problem": objective_func,
"problem_type": "spin",
"backend_name": backend_name, # such as "ibm_fez"
"options": options,
}

job = optimizer.run(**arguments)

3. Pobierz wynik

Rozwiązanie problemu optymalizacji jest dostarczane bezpośrednio przez optimizer.

print(job.result())

Wyświetlony zostanie słownik w następującej postaci:

{'solution': {'0': -1, '1': -1, '2': -1, '3': 1, '4': 1},
'solution_info': {'bitstring': '11100',
'cost': -13.8,
'seed_transpiler': 42,
'mapping': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}},
'prob_type': 'spin'}

Zauważ, że słownik solution wyświetla wektor wynikowy (x0,x1,x2,x3,x4)=(1,1,1,1,1)(x_0, x_1, x_2, x_3, x_4) = (-1, -1, -1, 1, 1).

Przykład 2: MaxCut

Wiele problemów grafowych, takich jak MaxCut czy maksymalny zbiór niezależny, to problemy NP-trudne i idealni kandydaci do testowania algorytmów kwantowych i sprzętu. Ten przykład demonstruje rozwiązanie problemu MaxCut dla grafu 3-regularnego za pomocą Quantum Optimizer.

Aby uruchomić ten przykład, musisz zainstalować pakiet networkx oprócz qiskit-ibm-catalog. Aby go zainstalować, uruchom następujące polecenie:

# %pip install networkx numpy

1. Utwórz funkcję celu

Zacznij od wygenerowania losowego grafu 3-regularnego. Dla tego grafu definiujemy funkcję celu problemu MaxCut.

import networkx as nx

# Create a random 3-regular graph
G = nx.random_regular_graph(3, 10, seed=42)

# Create the objective function for MaxCut in Ising formulation
def graph_to_ising_maxcut(G):
"""
Convert a NetworkX graph to an Ising Hamiltonian for the Max-Cut problem.
Args:
G (networkx.Graph): The input graph.
Returns:
dict: The objective function of the Ising model
"""
# Initialize the linear and quadratic coefficients
objective_func = {}
# Populate the coefficients
for i, j in G.edges:
objective_func[f"({i}, {j})"] = 0.5
return objective_func

objective_func = graph_to_ising_maxcut(G)

2. Uruchom Optimizer

Rozwiąż problem, uruchamiając optimizer.

options = {"shots": 5000, "num_iterations": 5, "use_session": True}

arguments = {
"problem": objective_func,
"problem_type": "spin",
"backend_name": backend_name, # such as "ibm_fez"
"options": options,
}

job = optimizer.run(**arguments)

3. Pobierz wynik

Pobierz wynik i odwzoruj ciąg bitów rozwiązania z powrotem na węzły oryginalnego grafu.

print(job.result())

Rozwiązanie problemu MaxCut jest bezpośrednio zawarte w pod-słowniku solution obiektu wynikowego

maxcut_solution = job.result()["solution"]

Przykład 3: Instancje benchmarkowe

Instancje benchmarkowe są dostępne na GitHub: Instancje benchmarkowe Kipu.

Instancje można załadować za pomocą biblioteki pygithub. Aby ją zainstalować, uruchom następujące polecenie:

# %pip install pygithub

Ścieżki do instancji benchmarkowych:

Maxcut:

  • 'maxcut/maxcut_28_nodes.json'
  • 'maxcut/maxcut_30_nodes.json'
  • 'maxcut/maxcut_32_nodes.json'
  • 'maxcut/maxcut_80_nodes.json'
  • 'maxcut/maxcut_100_nodes.json'
  • 'maxcut/maxcut_120_nodes.json'

HUBO:

  • 'HUBO/hubo1_marrakesh.json'
  • 'HUBO/hubo2_marrakesh.json'

Aby odtworzyć wydajność benchmarku dla instancji HUBO, wybierz Backend ibm_marrakesh i ustaw direct_qubit_mapping na True w pod-słowniku options. Poniższy przykład uruchamia instancję Maxcut z 32 węzłami.

from github import Github
import urllib
import json
import ast

repo = "Kipu-Quantum-GmbH/benchmark-instances"
path = "maxcut/maxcut_32_nodes.json"
gh = Github()
repo = gh.get_repo(repo)
branch = "main"
file = repo.get_contents(urllib.parse.quote(path), ref=branch)

# load json file with benchmark problem
problem_json = json.loads(file.decoded_content)

# convert objective function to compatible format
objective_func = {
key: ast.literal_eval(value) for key, value in problem_json.items()
}

# Setup configuration to run the optimizer
options = {
"shots": 5_000,
"num_iterations": 5,
"use_session": True,
"direct_qubit_mapping": False,
}

arguments = {
"problem": objective_func,
"problem_type": "spin",
"backend_name": "ibm_brisbane",
"options": options,
}

job = optimizer.run(**arguments)

result = job.result()

Przypadki użycia

Typowe przypadki użycia solvera optymalizacyjnego to kombinatoryczne problemy optymalizacyjne. Możesz rozwiązywać problemy z wielu branż, takich jak finanse, farmacja czy logistyka. Poniżej kilka przykładów.

Jeśli interesuje cię rozwiązanie konkretnego przypadku użycia i opracowanie dedykowanego odwzorowania, możemy ci w tym pomóc. Skontaktuj się z nami.

Uzyskaj wsparcie

W sprawie wsparcia skontaktuj się z support@kipu-quantum.com.

Następne kroki

Additional information

Iskay, podobnie jak nazwa naszej firmy Kipu Quantum, jest słowem peruwiańskim. Chociaż jesteśmy startupem z Niemiec, słowa te pochodzą z ojczyzny jednego z naszych współzałożycieli, gdzie Quipu był jednym z pierwszych urządzeń obliczeniowych stworzonych przez ludzkość 2000 lat p.n.e.