{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "e1dea188",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Finden Sie die maximale unabhängige Menge mit dem Aqarios Constrained Quantum Optimizer\"\n",
        "description: \"Verwenden Sie den „Aqarios Constrained Quantum Optimizer“, der auf iterativem Warm-Starting und XY-Mixern basiert, um das Problem der maximalen unabhängigen Menge auf der „ IBM Quantum “-Hardware zu lösen\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Aqarios QOBLIB Bucher forall */}\n",
        "\n",
        "<span id=\"find-the-maximum-independent-set-with-the-aqarios-constrained-quantum-optimizer\" />\n",
        "\n",
        "# Finden Sie die maximale unabhängige Menge mit dem Aqarios Constrained Quantum Optimizer\n",
        "\n",
        "<Admonition type=\"note\" title=\"Anmerkung\">\n",
        "  Qiskit Functions sind eine experimentelle Funktion, die ausschließlich Nutzern der Tarife „ IBM Quantum® Premium Plan “, „Flex Plan“ und „ On-Prem “ (über die IBM Quantum Platform -API) zur Verfügung steht. Sie befinden sich im Preview-Status und können sich noch ändern.\n",
        "</Admonition>\n",
        "\n",
        "Geschätzte *Laufzeit: 30 Sekunden auf einem Heron- r2 -Prozessor. (HINWEIS: Dies ist lediglich eine Schätzung. (Die Laufzeit kann variieren.)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be93797d",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "39ff36f6",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## Hintergrund\n",
        "\n",
        "Dieses Tutorial zeigt, wie man mithilfe des [Aqarios Constrained Quantum Optimizer](/docs/guides/aqarios-constrained-quantum-optimizer) [\\[1\\]](#references) die maximale unabhängige Menge eines Graphen ermittelt – ein kombinatorisches Optimierungsproblem mit Nebenbedingungen.\n",
        "Eine Instanz aus der QOBLIB-Benchmark-Bibliothek [\\[2\\]](#references) wird als binäres lineares Programm formuliert und an die Optimierungs-Anwendungsfunktion übergeben.\n",
        "Der Optimierer übernimmt alle Schritte der Umformulierung, Schaltungssynthese, Transpilierung und des iterativen Warmstarts intern (Einzelheiten siehe [\\[3\\]](#references) ).\n",
        "\n",
        "Das Tutorial behandelt die folgenden Schritte:\n",
        "\n",
        "1. Definieren Sie das Problem als lineares Programm unter Verwendung der Funktion `OptimizationProblem` aus [qiskit-addon-opt-mapper](https://github.com/qiskit/qiskit-addon-opt-mapper)\n",
        "2. Führen Sie die Quantenoptimierung mit dem „Aqarios Constrained Quantum Optimizer“ durch\n",
        "3. Ergebnisse abrufen und visualisieren\n",
        "\n",
        "<span id=\"the-maximum-independent-set-problem\" />\n",
        "\n",
        "### Das Problem der maximalen unabhängigen Menge\n",
        "\n",
        "Das Problem der maximalen unabhängigen Menge (MIS) stellt eine grundlegende Herausforderung in der kombinatorischen Optimierung dar.\n",
        "Formal gesehen besteht das Ziel bei einem gegebenen Graphen $G(V, E)$ darin, die größte Teilmenge von Knoten $V_I \\subset V$ zu finden, sodass keine zwei Knoten in $V_I$ durch eine Kante verbunden sind, wie in $\\nexists (u, v) \\in E : v \\in V_I \\wedge u \\in V_I$ dargestellt.\n",
        "Jedem Knoten wird eine binäre Entscheidungsvariable $x_i \\in \\{0, 1\\}$ zugewiesen, und für jede Kante wird eine Nebenbedingung $x_u + x_v \\leq 1$ eingeführt, die sicherstellt, dass höchstens ein Endpunkt jeder Kante ausgewählt wird.\n",
        "Das Problem lässt sich somit als folgendes Maximierungsproblem formulieren:\n",
        "\n",
        "$$\n",
        "\\max_{x_i} \\sum_{i \\in V} x_i \\qquad\\text{(find the largest set)}\\\\\n",
        "\\text{s.t.} \\quad x_u + x_v \\leq 1 \\quad \\forall (u, v) \\in E.\n",
        "$$\n",
        "\n",
        "MIS bietet ein breites Spektrum an praktischen Anwendungsmöglichkeiten. Bei der Planung von Funknetzen entspricht eine unabhängige Gruppe einer Gruppe von Sendern, die alle gleichzeitig senden können, ohne sich gegenseitig zu stören. Bei der Terminierung modelliert es die größte Menge an Aufgaben, die unter Berücksichtigung paarweiser Ressourcenkonflikte gleichzeitig ausgeführt werden können. In der Bioinformatik bezeichnet der Begriff Gruppen von Proteinen in einem Netzwerk, die untereinander keine Wechselwirkungen eingehen.\n",
        "\n",
        "Trotz seiner intuitiven Formulierung ist MIS NP-schwer, und selbst bei Graphen mit nur wenigen hundert Knoten lassen sich bestimmte Instanzen nur schwer exakt oder heuristisch lösen [\\[2\\]](#references).\n",
        "Das Problem führt zudem zu spärlichen Nebenbedingungsstrukturen, die sich gut für Hardware-Implementierungen der Quantenoptimierung eignen, was es zu einem attraktiven Benchmark für Quantencomputer der nahen Zukunft macht.\n",
        "\n",
        "<span id=\"aqarios-constrained-quantum-optimizer\" />\n",
        "\n",
        "### Aqarios Constrained Quantum Optimizer\n",
        "\n",
        "Der Standardansatz zur Einbettung eines binären Problems mit Nebenbedingungen in die Quantenoptimierung besteht darin, das Modell durch Hinzufügen von Straftermen in ein Format ohne Nebenbedingungen umzuwandeln: Jede verletzte Nebenbedingung $x_u + x_v \\leq 1$ trägt mit $2 x_u x_v$ zur Minimierungszielfunktion $-\\sum_i x_i$ bei. Dies wird automatisch von der Qiskit-Funktion „Constrained Quantum Optimizer“ übernommen.\n",
        "\n",
        "Über diese Standardtransformation hinaus identifiziert der Optimierer **Cliquen** im Beschränkungsgraphen. Eine Clique ist eine Menge von Knoten $V_C$, bei der jedes Knotenpaar durch eine Kante verbunden ist. Folglich können die paarweisen Nebenbedingungen $\\binom{|V_C|}{2}$ $x_u + x_v \\leq 1 \\;\\forall (u,v) \\in E_C$ durch eine einzige, strengere Nebenbedingung $\\sum_{i \\in V_C} x_i \\leq 1$ ersetzt werden. Durch die Einführung einer Slack-Variablen $y$ wird daraus eine Gleichung $\\sum_i x_i + y = 1$, die die Form einer One-Hot-Nebenbedingung annimmt, die in QAOA mithilfe von **XY-Mixern** [\\[3\\]](#references) direkt durchgesetzt werden kann. Dadurch wird der Suchraum verkleinert und die Notwendigkeit von Straftermen für diese Nebenbedingungen vermieden, was die Qualität der Lösung verbessert.\n",
        "\n",
        "Zudem werden Variablen, die nur mit einem einzigen Nachbarn verbunden sind, als „**pendant** nodes“ bezeichnet und vom Algorithmus vor der Quantenausführung deterministisch festgelegt, wodurch sich die effektive Problemgröße weiter verringert.\n",
        "\n",
        "Der „Constrained Quantum Optimizer“ nutzt einen **iterativen Warm-Start-Ansatz**, der mit XY-Mischern kompatibel ist [\\[1\\]](#references) und den Suchraum schrittweise eingrenzt, indem er die Verteilung der Quantenzustände im Laufe der Iterationen in Richtung vielversprechender Lösungsbereiche verschiebt. Dies ermöglicht die Verwendung von **QAOA-Parametern mit festem Winkel**, wodurch ein variationales Parametertraining entfällt. Der Gesamtbedarf an Quantenressourcen hängt ausschließlich von der Anzahl der Warm-Start-Iterationen ab, was bedeutet, dass sich die Quantenkosten leicht steuern lassen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "01da2a6e",
      "metadata": {
        "lines_to_next_cell": 0
      },
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## Anforderungen\n",
        "\n",
        "Bevor Sie mit dieser Anleitung beginnen, stellen Sie bitte sicher, dass die folgenden Voraussetzungen erfüllt sind:\n",
        "\n",
        "* Qiskit Runtime (`pip install qiskit-ibm-runtime`)\n",
        "* Qiskit Functions Catalog IBM Client (`pip install qiskit-ibm-catalog`)\n",
        "* Qiskit-Add-on „Optimization Mapper“ (`pip install qiskit-addon-opt-mapper`)\n",
        "* Numpy (`pip install numpy`)\n",
        "* Matplotlib (`pip install matplotlib`)\n",
        "* NetworkX (`pip install networkx`)\n",
        "\n",
        "Optional müssen Sie für den [Anhang](#appendix-problem-statement-with-luna-model) Folgendes installieren:\n",
        "\n",
        "* Luna-Modell (`pip install luna-model`)\n",
        "\n",
        "<span id=\"setup\" />\n",
        "\n",
        "## Einrichtung\n",
        "\n",
        "Importiere alle erforderlichen Abhängigkeiten.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "3fe5037e-e02b-40cb-bba7-7349d729df53",
      "metadata": {},
      "outputs": [],
      "source": [
        "import networkx as nx\n",
        "import urllib.request\n",
        "\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "from qiskit_addon_opt_mapper import OptimizationProblem\n",
        "from qiskit_addon_opt_mapper.applications import IndependentSet\n",
        "from qiskit_addon_opt_mapper.translators import to_docplex_mp"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d47802c3",
      "metadata": {},
      "source": [
        "Melden Sie sich zunächst mit Ihrem [API-Schlüssel für „ IBM Quantum “ an.](http://quantum.cloud.ibm.com/) Wählen Sie anschließend die Qiskit-Funktion wie folgt aus. (Dieser Code setzt voraus, dass Sie [Ihr Konto](/docs/guides/functions-get-started#install-qiskit-functions-catalog-client) bereits in Ihrer lokalen Umgebung gespeichert haben.)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "2e6b3761",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[QiskitFunction(aqarios/constrained-quantum-optimizer)]"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "catalog = QiskitFunctionsCatalog(channel=\"ibm_quantum_platform\")\n",
        "\n",
        "# Verify that you have access to the function\n",
        "catalog.list()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "2b3688f0",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Load the function\n",
        "optimizer = catalog.load(\"aqarios/constrained-quantum-optimizer\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "bd0fd445",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[<IBMBackend('ibm_pittsburgh')>,\n",
              " <IBMBackend('ibm_boston')>,\n",
              " <IBMBackend('ibm_phoenix')>,\n",
              " <IBMBackend('ibm_fez')>,\n",
              " <IBMBackend('ibm_miami')>,\n",
              " <IBMBackend('ibm_marrakesh')>,\n",
              " <IBMBackend('ibm_kingston')>]"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Check the list of backends you have access to\n",
        "catalog.backends()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "e50deb54",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Select the backend you want to use\n",
        "backend = catalog.backend(\"ibm_pittsburgh\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5435d391",
      "metadata": {},
      "source": [
        "<span id=\"step-1-map-classical-inputs-to-quantum-problem\" />\n",
        "\n",
        "## Schritt 1: Abbildung klassischer Eingaben auf das Quantenproblem\n",
        "\n",
        "Das Problem wird als **LP-Datei** formuliert, einem gängigen Format für Optimierungsprobleme, das als Eingabe für den Aqarios Constrained Quantum Optimizer dient. Neben LP-Dateien unterstützt die Funktion auch **MPS-Dateien** und native **Luna-Modelldarstellungen**.\n",
        "Die LP-Datei wird in den folgenden Schritten erstellt:\n",
        "\n",
        "1. Eine Graph-Instanz aus der QOBLIB [\\[2\\]](#references) abrufen\n",
        "2. Das Optimierungsproblem modellieren\n",
        "3. LP-Datei erstellen\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c773d45b",
      "metadata": {},
      "source": [
        "<span id=\"load-the-problem-instance-graph\" />\n",
        "\n",
        "### Den Graphen der Probleminstanz laden\n",
        "\n",
        "Die Grafen werden im DIMACS-Format `.gph` angegeben, einem zeilenbasierten Format, bei dem Zeilen, die mit beginnen, Kanten `e` definieren, Zeilen, die mit beginnen, den Problemkopf definieren `p` , und Zeilen, die mit beginnen, Kommentare sind `c` :\n",
        "\n",
        "```\n",
        "c some-comment\n",
        "p edge 3 2\n",
        "e 1 2\n",
        "e 2 3\n",
        "...\n",
        "```\n",
        "\n",
        "Die Datei `.gph` kann mithilfe der folgenden Funktion aus dem QOBLIB-Repository heruntergeladen werden; dabei wird sie zudem in einen „ NetworkX “-Graph geparst. Beachten Sie, dass das DIMACS-Format eine Knotenbeschriftung mit 1 als Startwert verwendet, die hier in eine Indizierung mit 0 als Startwert umgewandelt wird.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "8e09bff6-0d5b-4ce5-869b-449755d7edad",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Loading graph with 186 nodes and 280 edges.\n"
          ]
        }
      ],
      "source": [
        "URL_BASE = \"https://raw.githubusercontent.com/ZIB-AOPT/QOBLIB/refs/heads/main/07-independentset/instances/\"\n",
        "\n",
        "\n",
        "def fetch_qoblib_graph(name: str) -> nx.Graph:\n",
        "    \"\"\"Fetch and parse the QOBLIB graph file.\"\"\"\n",
        "    # Download the .gph file\n",
        "    file, _ = urllib.request.urlretrieve(URL_BASE + f\"{name}.gph\")\n",
        "    with open(file) as f:\n",
        "        # Read the file contents\n",
        "        lines = f.readlines()\n",
        "\n",
        "    # Skip comments\n",
        "    lines = [line for line in lines if not line.startswith(\"c\")]\n",
        "\n",
        "    # Read graph definition\n",
        "    _, _, num_nodes, num_edges = lines[0].split()\n",
        "    print(f\"Loading graph with {num_nodes} nodes and {num_edges} edges.\")\n",
        "\n",
        "    # Parse edge information\n",
        "    # The .gph format starts node labeling with 1; we need 0 here, so we subtract one.\n",
        "    split_edges = (line.split() for line in lines[1:])\n",
        "    edges = [(int(u) - 1, int(v) - 1) for _, u, v in split_edges]\n",
        "\n",
        "    return nx.Graph(edges)\n",
        "\n",
        "\n",
        "graph_name = \"es60fst02\"\n",
        "graph = fetch_qoblib_graph(graph_name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2851abad",
      "metadata": {},
      "source": [
        "In diesem Beispiel wird die Instanz `es60fst02` aus QOBLIB verwendet, ein Graph mit 186 Knoten und 280 Kanten. Dank der vom Constrained Quantum Optimizer durchgeführten Vorverarbeitungsschritte lässt sich diese Instanz auf Heron-Geräten mit 156 Qubits lösen. Die Grafik lässt sich mit matplotlib visualisieren:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "182c672d-bab4-48e7-93c1-5e19dc9226ab",
      "metadata": {
        "lines_to_next_cell": 2
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/find-the-maximum-independent-set-with-aqarios-constrained-quantum-optimizer/extracted-outputs/182c672d-bab4-48e7-93c1-5e19dc9226ab-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Keep layout for later reuse\n",
        "layout = nx.spring_layout(graph, seed=1)\n",
        "nx.draw(graph, layout, node_size=40)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "59456755",
      "metadata": {},
      "source": [
        "<span id=\"construct-the-optimization-problem\" />\n",
        "\n",
        "### Formulieren Sie das Optimierungsproblem\n",
        "\n",
        "Das Problem der maximalen unabhängigen Menge lässt sich direkt mithilfe von formulieren `OptimizationProblem`. Jeder Knoten des Graphen wird zu einer binären Entscheidungsvariablen, und jede Kante führt eine Nebenbedingung ein, die sicherstellt, dass höchstens einer ihrer Endpunkte ausgewählt wird:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "d5363fd3",
      "metadata": {
        "lines_to_next_cell": 2
      },
      "outputs": [],
      "source": [
        "# Create an OptimizationProblem instance\n",
        "mis_problem = OptimizationProblem(\"MIS\")\n",
        "\n",
        "# Add a binary variable for each node\n",
        "x = mis_problem.binary_var_list(graph.number_of_nodes())\n",
        "\n",
        "# Maximize the sum of all node variables\n",
        "mis_problem.maximize(linear={xi.name: 1 for xi in x})\n",
        "\n",
        "# Add '<= 1' constraints for each edge\n",
        "for u, v in graph.edges:\n",
        "    mis_problem.linear_constraint({x[u].name: 1, x[v].name: 1}, \"<=\", 1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7f9a8247",
      "metadata": {},
      "source": [
        "<span id=\"a-shortcut\" />\n",
        "\n",
        "#### Eine Abkürzung\n",
        "\n",
        "Das Paket [`qiskit-addon-opt-mapper`](https://qiskit.github.io/qiskit-addon-opt-mapper/) stellt eine vorgefertigte Anwendungsklasse für das Problem der maximalen unabhängigen Menge bereit, wodurch sich die obige Formulierung auf einen einzigen Aufruf vereinfachen lässt:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "01e2a4e0",
      "metadata": {},
      "outputs": [],
      "source": [
        "mis = IndependentSet(graph)\n",
        "mis_problem = mis.to_optimization_problem()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c6870d4e",
      "metadata": {},
      "source": [
        "<span id=\"translate-the-problem-to-an-lp-file\" />\n",
        "\n",
        "### Übersetzen Sie die Aufgabe in eine LP-Datei\n",
        "\n",
        "Das Programm selbst `OptimizationProblem` unterstützt zwar keinen Export von LP-Dateien, ist jedoch mit [DOcplex](https://www.ibm.com/docs/de/icos/22.1.2?topic=docplex-python-modeling-api) kompatibel, das diese Funktion bietet. Um den Inhalt der LP-Datei zu erstellen, sind lediglich zwei Zeilen erforderlich:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "bf4d697a",
      "metadata": {
        "lines_to_next_cell": 0
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\\ This file has been generated by DOcplex\n",
            "\\ ENCODING=ISO-8859-1\n",
            "\\Problem name: Independent set\n",
            "\n",
            "Maximize\n",
            " 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\n",
            "      + x_12 + x_13 + x_14 + x_15 + x_16 + x_17 + x_18 + x_19 + x_20 + x_21\n",
            "      + x_22 + x_23 + x_24 + x_25 + x_26 + x_27 + x_28 + x_29 + x_30 + x_31\n",
            "      + x_32 + x_33 + x_34 + x_35 + x_36 + x_37 + x_38 + x_39 + x_40 + x_41\n",
            "      + x_42 + x_43 + x_44 + x_45 + x_46 + x_47 + x_48 + x_49 + x_50 + x_51\n",
            "      + x_52 + x_53 + x_54 + x_55 + x_56 + x_57 + x_58 + x_59 + x_60 + x_61\n",
            "      + x_62 + x_63 + x_64 + x_65 + x_66 + x_67 + x_68 + x_69 + x_70 + x_71\n",
            "      + x_72 + x_73 + x_74 + x_75 + x_76 + x_77 + x_78 + x_79 + x_80 + x_81\n",
            "      + x_82 + x_83 + x_84 + x_85 + x_86 + x_87 + x_88 + x_89 + x_90 + x_91\n",
            "      + x_92 + x_93 + x_94 + x_95 + x_96 + x_97 + x_98 + x_99 + x_100 + x_101\n",
            "      + x_102 + x_103 + x_104 + x_105 + x_106 + x_107 + x_108 + x_109 + x_110\n",
            "      + x_111 + x_112 + x_113 + x_114 + x_115 + x_116 + x_117 + x_118 + x_119\n",
            "      + x_120 + x_121 + x_122 + x_123 + x_124 + x_125 + x_126 + x_127 + x_128\n",
            "      + x_129 + x_130 + x_131 + x_132 + x_133 + x_134 + x_135 + x_136 + x_137\n",
            "      + x_138 + x_139 + x_140 + x_141 + x_142 + x_143 + x_144 + x_145 + x_146\n",
            "      + x_147 + x_148 + x_149 + x_150 + x_151 + x_152 + x_153 + x_154 + x_155\n",
            "      + x_156 + x_157 + x_158 + x_159 + x_160 + x_161 + x_162 + x_163 + x_164\n",
            "      + x_165 + x_166 + x_167 + x_168 + x_169 + x_170 + x_171 + x_172 + x_173\n",
            "      + x_174 + x_175 + x_176 + x_177 + x_178 + x_179 + x_180 + x_181 + x_182\n",
            "      + x_183 + x_184 + x_185\n",
            "Subject To\n",
            " c0: x_60 + x_61 <= 1\n",
            " c1: x_14 + x_60 <= 1\n",
            " c2: x_7 + x_60 <= 1\n",
            " c3: x_7 + x_61 <= 1\n",
            " c4: x_61 + x_62 <= 1\n",
            " c5: x_61 + x_64 <= 1\n",
            " c6: x_14 + x_62 <= 1\n",
            " c7: x_62 + x_65 <= 1\n",
            " c8: x_23 + x_63 <= 1\n",
            " c9: x_53 + x_63 <= 1\n",
            " c10: x_39 + x_63 <= 1\n",
            " c11: x_7 + x_68 <= 1\n",
            " c12: x_18 + x_68 <= 1\n",
            " c13: x_68 + x_69 <= 1\n",
            " c14: x_68 + x_72 <= 1\n",
            " c15: x_64 + x_65 <= 1\n",
            " c16: x_64 + x_69 <= 1\n",
            " c17: x_65 + x_66 <= 1\n",
            " c18: x_51 + x_53 <= 1\n",
            " c19: x_69 + x_73 <= 1\n",
            " c20: x_66 + x_67 <= 1\n",
            " c21: x_42 + x_66 <= 1\n",
            " c22: x_67 + x_75 <= 1\n",
            " c23: x_43 + x_67 <= 1\n",
            " c24: x_42 + x_75 <= 1\n",
            " c25: x_75 + x_83 <= 1\n",
            " c26: x_12 + x_51 <= 1\n",
            " c27: x_18 + x_70 <= 1\n",
            " c28: x_18 + x_26 <= 1\n",
            " c29: x_70 + x_71 <= 1\n",
            " c30: x_70 + x_76 <= 1\n",
            " c31: x_71 + x_72 <= 1\n",
            " c32: x_72 + x_73 <= 1\n",
            " c33: x_72 + x_78 <= 1\n",
            "...\n"
          ]
        }
      ],
      "source": [
        "mp_model = to_docplex_mp(mis_problem)\n",
        "lp_str = mp_model.export_as_lp_string()\n",
        "\n",
        "print(\"\\n\".join(lp_str.split(\"\\n\")[:60]))\n",
        "print(\"...\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0c6ca33d",
      "metadata": {},
      "source": [
        "Dieses Format ist im „Constrained Quantum Optimizer“ nativ unterstützt.\n",
        "\n",
        "<span id=\"step-2-optimize-problem-for-quantum-hardware-execution\" />\n",
        "\n",
        "## Schritt 2: Optimierung des Problems für die Ausführung auf Quantenhardware\n",
        "\n",
        "Die gesamte Schaltungssynthese, -optimierung und -transpilierung wird von der Funktion nativ übernommen. Die Argumente, mit denen die Funktion aufgerufen werden muss, finden Sie im [Abschnitt „Eingaben“](/docs/api/functions/aqarios-constrained-quantum-optimizer#inputs) der API-Referenz.\n",
        "\n",
        "Informationen zur Feinabstimmung des Algorithmus finden Sie in der [Liste „Optionen“](/docs/api/functions/aqarios-constrained-quantum-optimizer#options-list) in der API-Referenz. Wenn Sie möchten, dass die Schaltkreisabbildung über mehrere Durchläufe hinweg reproduzierbar ist, legen Sie die Option `seed_transpiler` fest.\n",
        "\n",
        "Weitere Informationen finden Sie im [Handbuch](/docs/guides/aqarios-constrained-quantum-optimizer) und in [der API-Referenz](/docs/api/functions/aqarios-constrained-quantum-optimizer) zum Aqarios Constrained Quantum Optimizer.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "241b80a6",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "## Schritt 3: Mit „ Qiskit primitives “ ausführen\n",
        "\n",
        "Die LP-Datei kann nun an den Optimierer übermittelt werden:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "02469f27-1ea9-4fa2-8412-3e7c5ec1a59f",
      "metadata": {
        "lines_to_next_cell": 0
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job ID: 87ec08b9-6275-40fa-be94-340a0a916bf1\n"
          ]
        }
      ],
      "source": [
        "job = optimizer.run(problem=lp_str, backend_name=backend.name)\n",
        "\n",
        "print(f\"Job ID: {job.job_id}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4804bb92",
      "metadata": {},
      "source": [
        "Intern durchläuft der Algorithmus die folgenden Schritte:\n",
        "\n",
        "1. **Vorverarbeitung** :\n",
        "   * Behebbare Variablen reduzieren\n",
        "   * Cliquen finden\n",
        "   * Einschränkungstypen identifizieren\n",
        "   * Strafkoeffizienten für Strafklauseln bewerten\n",
        "   * Beschränkungstransformationen anwenden\n",
        "   * Schaltung mit Methoden zur Durchsetzung von Beschränkungen synthetisieren\n",
        "   * Annäherung an das Problem und Transpilierung\n",
        "2. **Parallele Ketten von iterativen Schleifen** :\n",
        "   * Beispiel aus einer Schaltung mit festen Parametern\n",
        "   * Nachbearbeitung anwenden\n",
        "   * Die Wahrscheinlichkeiten für einen Warmstart bewerten und neu festlegen\n",
        "3. **Nachbearbeitung** :\n",
        "   * Finden Sie die besten Beispiele und prüfen Sie die Machbarkeit in Bezug auf das Ausgangsproblem\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "25fa45d3",
      "metadata": {},
      "source": [
        "<span id=\"monitor-the-progress\" />\n",
        "\n",
        "### Den Fortschritt überwachen\n",
        "\n",
        "Lesen Sie die folgenden Abschnitte auf der Seite „Erste Schritte mit Qiskit Functions “, um den Fortschritt Ihres Auftrags zu überwachen:\n",
        "\n",
        "* [Auftragsstatus prüfen](/docs/guides/functions-get-started#check-job-status)\n",
        "* [Ergebnisse abrufen](/docs/guides/functions-get-started#retrieve-results)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "416cf0c0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'QUEUED'"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Monitor the job status\n",
        "job.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8378a14f",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-and-return-results-in-desired-classical-format\" />\n",
        "\n",
        "## Schritt 4: Nachbearbeitung und Ausgabe der Ergebnisse im gewünschten klassischen Format\n",
        "\n",
        "Die Ausgabe besteht aus einem Wörterbuch, dessen Felder im [Abschnitt „Ausgaben“](/docs/api/functions/aqarios-constrained-quantum-optimizer#outputs) der API-Referenz beschrieben sind.\n",
        "\n",
        "Wenn die Liste [`solutions`](/docs/api/functions/aqarios-constrained-quantum-optimizer#output-structure) mehr als einen Eintrag enthält, wurden mehrere entartete Optima gefunden. Hier wird nur die erste Lösung betrachtet, die über den Variablennamen angesprochen wird. Die gleichen Lösungen sind auch als Bitfolgen in verfügbar `solution_bitstrings`, wobei die Zeichenposition der jeweiligen Variablen angibt `metadata.solver_info.variable_mapping` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "fe8a3b9d",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The found maximum independent set of es60fst02 contains: 88 nodes and is feasible.\n",
            "{100 103 107 109 111 113 115 118 121 123 124 127 129 130 132 133 138 142 144 148 149 155 156 16 161 162 165 167 169 170 175 28 31 33 35 36 47 50 58 59 60 62 64 66 68 71 73 75 78 79 84 85 87 90 91 93 94 95 39 5 27 23 43 15 22 9 4 56 32 30 53 26 17 54 1 37 41 49 34 11 139 153 12 3 6 57 20 44}\n"
          ]
        }
      ],
      "source": [
        "# Retrieve the job result\n",
        "result = job.result()\n",
        "\n",
        "# Retrieve the first solution from the result\n",
        "solution = result[\"solutions\"][0]\n",
        "\n",
        "print(f\"The found maximum independent set of {graph_name} contains:\", end=\" \")\n",
        "print(\n",
        "    f\"{int(result['objective_value'])} nodes and is {'feasible' if result['feasible'] else 'infeasible'}.\"\n",
        ")\n",
        "print(\"{\" + \" \".join(k[2:] for k, v in solution.items() if v == 1) + \"}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e0ac4233",
      "metadata": {},
      "source": [
        "<span id=\"visualization\" />\n",
        "\n",
        "### Visualisierung\n",
        "\n",
        "Die ermittelte unabhängige Menge lässt sich visualisieren, indem die ausgewählten Knoten im Graphen hervorgehoben werden:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "f068c750",
      "metadata": {
        "lines_to_next_cell": 2
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/find-the-maximum-independent-set-with-aqarios-constrained-quantum-optimizer/extracted-outputs/f068c750-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Color all selected nodes in orange\n",
        "node_map = {\n",
        "    int(k.split(\"_\")[1]): \"tab:orange\" if v else \"tab:blue\"\n",
        "    for k, v in solution.items()\n",
        "}\n",
        "node_colors = [node_map[k] for k in graph.nodes]\n",
        "\n",
        "# Draw with the same layout used before\n",
        "nx.draw(graph, layout, node_size=40, node_color=node_colors)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1463b529",
      "metadata": {},
      "source": [
        "<span id=\"appendix-problem-statement-with-luna-model\" />\n",
        "\n",
        "## Anhang: Problemstellung mit dem Luna-Modell\n",
        "\n",
        "Zusätzlich zu dem oben gezeigten `qiskit-addon-opt-mapper` Ansatz akzeptiert die Qiskit-Funktion auch Modelle, die mit Luna Model [\\[4\\]](#references), dem Modellierungs-SDK von Aqarios, erstellt wurden.\n",
        "Nach der Installation des Pakets `luna-model` „ PyPI “ importieren Sie es wie folgt:\n",
        "\n",
        "**Einrichten:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "299a6d7c",
      "metadata": {},
      "outputs": [],
      "source": [
        "from luna_model import Model, Sense\n",
        "import numpy as np"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "03a63f0d",
      "metadata": {},
      "source": [
        "Das Modell wird dann anhand des Graphen auf dieselbe Weise wie bei … erstellt `qiskit-addon-opt-mapper`:\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fbf74687",
      "metadata": {},
      "source": [
        "**Erstellen Sie das Modell:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "cf52944f-8908-4b4e-8e65-556fbe3b7a38",
      "metadata": {},
      "outputs": [],
      "source": [
        "edges = np.array(graph.edges)\n",
        "\n",
        "# Create the optimization model with a name\n",
        "model = Model(name=f\"MIS-{graph_name}\", sense=Sense.MAX)\n",
        "# Add binary variables\n",
        "x = model.add_variables(\"x\", graph.number_of_nodes())\n",
        "# Set the objective\n",
        "model.objective = x.sum()\n",
        "\n",
        "# Use numpy like batch generation of constraints\n",
        "model.add_constraints(x[edges].sum(axis=1) <= 1)\n",
        "\n",
        "input_str = model.encode_b64()\n",
        "\n",
        "# optimizer.run(problem=input_str, backend_name=\"ibm_fez\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "42730c89",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## NächsSchr\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Empfehlungen\">\n",
        "  * Eine detaillierte Anleitung zu allen Funktionen finden Sie im [Handbuch zum Aqarios Constrained Quantum Optimizer](/docs/guides/aqarios-constrained-quantum-optimizer).\n",
        "  * In der [API-Referenz](/docs/api/functions/aqarios-constrained-quantum-optimizer) finden Sie eine vollständige Liste der Eingabeparameter und Ausgabefelder.\n",
        "  * Probieren Sie die Algorithmusoptionen (`reps`, `num_parallel`, `shots`, `postprocessing_level`) an Ihrem eigenen binären Optimierungsproblem mit Nebenbedingungen aus, um deren Auswirkungen auf die Lösungsqualität und die Laufzeit zu bewerten.\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"references\" />\n",
        "\n",
        "## Referenzen\n",
        "\n",
        "1. IBM Quantum : [*Leitfaden zum Aqarios Constrained Quantum Optimizer*](/docs/guides/aqarios-constrained-quantum-optimizer)\n",
        "2. Koch et al. (2026), *„The Quantum Optimization Benchmarking Library“* [10.1038/s43588-026-00991-1](https://doi.org/10.1038/s43588-026-00991-1)\n",
        "3. Bucher et al. (2026), *„Constrained Quantum Optimization via Iterative Warm-Start XY-Mixers“* [10.1088/1367-2630/ae8ea2](https://doi.org/10.1088/1367-2630/ae8ea2)\n",
        "4. Aqarios „ GmbH, “ – [*Luna-Modell-Dokumentation*](https://docs.aqarios.com/luna-model)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}