{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b6d1e3ec",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Binäre Optimierung höherer Ordnung mit dem Optimierungslöser von Q-CTRL\"\n",
        "description: \"Lösen Sie ein Quantenoptimierungsproblem im Versorgungsmaßstab mit dem Optimization Solver, einer Qiskit-Funktion von Q-CTRL Fire Opal\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore nrows ncols lambdify ILOG histtype stepfilled */}\n",
        "\n",
        "<span id=\"higher-order-binary-optimization-with-q-ctrls-optimization-solver\" />\n",
        "\n",
        "# Binäre Optimierung höherer Ordnung mit dem Optimierungslöser von Q-CTRL\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a6f69b77",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Anmerkung\">\n",
        "  Qiskit-Funktionen sind eine experimentelle Funktion, die nur für Benutzer des IBM Quantum® Premium Plan, Flex Plan und On-Prem (über IBM Quantum Platform API) Plan verfügbar ist. Sie befinden sich im Status einer Vorabversion und können sich noch ändern.\n",
        "</Admonition>\n",
        "\n",
        "*Geschätzte Nutzungsdauer: 24 Minuten auf einem Heron r2 Prozessor. (HINWEIS: Dies ist nur eine Schätzung. Ihre Laufzeit kann variieren.)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8bf80006",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## Hintergrund\n",
        "\n",
        "In diesem Tutorial wird gezeigt[,](/docs/guides/q-ctrl-optimization-solver) wie man ein binäres Optimierungsproblem höherer Ordnung (HOBO) mithilfe des „Optimization Solver“ löst, einer Qiskit-Funktion von Q-CTRL Fire Opal. Das in diesem Tutorial vorgestellte Beispiel ist ein Optimierungsproblem, bei dem es darum geht, die Grundzustandsenergie eines Ising-Modells mit 156 Qubits und zufälligen Bindungen sowie kubischen Termen zu ermitteln. Der Optimierungslöser kann auf Probleme angewendet werden, die als unterstützte binäre Optimierungsziele formuliert sind, darunter Formulierungen für den Lastausgleich im Stromnetz, die Routenoptimierung in der Logistik oder die Minimierung von Fertigungsabfällen.\n",
        "\n",
        "Die Optimierung automatisiert die hardwarenahen Implementierungsschritte zur Lösung von Optimierungsproblemen auf Quanten-Hardware vollständig, und durch die Nutzung des [Leistungsmanagements](/docs/guides/q-ctrl-performance-management) für die Quantenausführung werden genaue Lösungen im Versorgungsmaßstab erzielt. Eine detaillierte Zusammenfassung des gesamten Optimization Solver-Workflows und der Benchmarking-Ergebnisse finden Sie im [veröffentlichten Manuskript](https://arxiv.org/abs/2406.01743).\n",
        "\n",
        "Diese Anleitung führt Sie durch die folgenden Schritte:\n",
        "\n",
        "1. Definieren Sie das Problem als eine Zielfunktion\n",
        "2. Führen Sie den hybriden Algorithmus mit dem Fire Opal Optimization Solver aus\n",
        "3. Ergebnisse bewerten\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "55b94021",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## Anforderungen\n",
        "\n",
        "Vergewissern Sie sich vor Beginn dieses Tutorials, dass Sie die folgenden Komponenten installiert haben:\n",
        "\n",
        "* Qiskit-Funktionen (`pip install qiskit-ibm-catalog`)\n",
        "* SymPy (`pip install sympy`)\n",
        "\n",
        "Außerdem müssen Sie Zugang zur Funktion Optimization Solver erhalten. [Füllen Sie das Formular aus](/functions?id=q-ctrl-optimization-solver), um Zugang zu beantragen.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "7db2e559",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Einrichtung\n",
        "\n",
        "Importieren Sie zunächst die erforderlichen Pakete und Werkzeuge.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "c262cb27",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Qiskit Functions Catalog\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "# SymPy tools for constructing objective function\n",
        "from sympy import Poly\n",
        "from sympy import symbols, srepr\n",
        "\n",
        "# Tools for plotting and evaluating results\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "from sympy import lambdify"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "df157bba",
      "metadata": {},
      "source": [
        "Legen Sie Ihre Anmeldedaten für „ [IBM Quantum Platform](/) “ fest, die im gesamten Tutorial zur Authentifizierung bei „ IBM Quantum Compute Service“ und „ Qiskit Functions “ verwendet werden.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b92bd67d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Credentials\n",
        "\n",
        "# For `token`, use the 44-character API_KEY you created\n",
        "# and saved from the IBM Quantum Platform Home dashboard\n",
        "token = \"<YOUR-API_KEY>\"\n",
        "instance = \"<YOUR_CRN>\""
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "988ee237",
      "metadata": {},
      "source": [
        "<span id=\"step-1-define-the-problem-as-an-objective-function\" />\n",
        "\n",
        "## Schritt 1: Definieren Sie das Problem als Zielfunktion\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6c9bffae",
      "metadata": {},
      "source": [
        "Der Optimierungslöser akzeptiert entweder eine Zielfunktion oder ein Diagramm als Eingabe. In diesem Tutorium wird das Ising-Spin-Glass-Minimierungsproblem als Zielfunktion definiert und auf die Heavy-Hex-Topologie von IBM® zugeschnitten.\n",
        "\n",
        "Da diese Zielfunktion kubische, quadratische und lineare Terme enthält, fällt sie in die Klasse der HOBO-Probleme, die bekanntermaßen wesentlich komplizierter zu lösen sind als herkömmliche quadratische unconstrained binary optimization (QUBO) Probleme.\n",
        "\n",
        "Eine ausführliche Erörterung der Konstruktion der Problemstellung und der bisherigen Ergebnisse des Optimization Solver findet sich in [diesem technischen Manuskript](https://arxiv.org/abs/2406.01743). Das Problem wurde ursprünglich im Rahmen einer [vom Los Alamos National Laboratory veröffentlichten Arbeit](https://arxiv.org/abs/2312.00997) definiert und bewertet und wurde so angepasst, dass die volle Bandbreite der 156-Qubit IBM Quantum Heron Prozessoren genutzt werden kann.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 42,
      "id": "0ad66539",
      "metadata": {},
      "outputs": [],
      "source": [
        "qubit_count = 156\n",
        "\n",
        "# Create symbolic variables to represent qubits\n",
        "x = symbols([f\"x[{i}]\" for i in range(qubit_count)])\n",
        "\n",
        "# # Define a polynomial representing a spin glass model\n",
        "spin_glass_poly = Poly(\n",
        "    -4 * x[0] * x[1]\n",
        "    - 8 * x[1] * x[2] * x[3]\n",
        "    + 8 * x[1] * x[2]\n",
        "    + 4 * x[1] * x[3]\n",
        "    - 4 * x[2]\n",
        "    + 8 * x[3] * x[4] * x[5]\n",
        "    - 4 * x[3] * x[5]\n",
        "    - 8 * x[3] * x[16] * x[23]\n",
        "    + 4 * x[3] * x[23]\n",
        "    - 2 * x[3]\n",
        "    - 4 * x[4]\n",
        "    - 8 * x[5] * x[6] * x[7]\n",
        "    + 8 * x[5] * x[6]\n",
        "    + 4 * x[5] * x[7]\n",
        "    - 2 * x[5]\n",
        "    + 8 * x[6] * x[7]\n",
        "    - 4 * x[6]\n",
        "    - 8 * x[7] * x[8] * x[9]\n",
        "    + 4 * x[7] * x[9]\n",
        "    - 8 * x[7] * x[17] * x[27]\n",
        "    + 4 * x[7] * x[27]\n",
        "    - 6 * x[7]\n",
        "    + 8 * x[8] * x[9]\n",
        "    + 8 * x[9] * x[10] * x[11]\n",
        "    - 4 * x[9] * x[11]\n",
        "    - 2 * x[9]\n",
        "    - 8 * x[10] * x[11]\n",
        "    + 4 * x[10]\n",
        "    - 8 * x[11] * x[12] * x[13]\n",
        "    + 4 * x[11] * x[13]\n",
        "    - 8 * x[11] * x[18] * x[31]\n",
        "    + 8 * x[11] * x[18]\n",
        "    + 4 * x[11] * x[31]\n",
        "    - 2 * x[11]\n",
        "    + 8 * x[12] * x[13]\n",
        "    + 8 * x[13] * x[14] * x[15]\n",
        "    - 4 * x[13] * x[15]\n",
        "    - 2 * x[13]\n",
        "    - 8 * x[14] * x[15]\n",
        "    + 4 * x[14]\n",
        "    - 8 * x[15] * x[19] * x[35]\n",
        "    + 8 * x[15] * x[19]\n",
        "    + 4 * x[15] * x[35]\n",
        "    - 2 * x[15]\n",
        "    + 8 * x[16] * x[23]\n",
        "    + 8 * x[17] * x[27]\n",
        "    - 4 * x[17]\n",
        "    + 8 * x[18] * x[31]\n",
        "    - 8 * x[18]\n",
        "    + 8 * x[19] * x[35]\n",
        "    - 8 * x[19]\n",
        "    + 4 * x[20] * x[21]\n",
        "    - 4 * x[20]\n",
        "    - 8 * x[21] * x[22] * x[23]\n",
        "    + 8 * x[21] * x[22]\n",
        "    + 4 * x[21] * x[23]\n",
        "    - 8 * x[21] * x[36] * x[41]\n",
        "    + 4 * x[21] * x[41]\n",
        "    - 4 * x[21]\n",
        "    + 8 * x[22] * x[23]\n",
        "    - 8 * x[22]\n",
        "    + 8 * x[23] * x[24] * x[25]\n",
        "    - 4 * x[23] * x[25]\n",
        "    - 10 * x[23]\n",
        "    - 8 * x[24] * x[25]\n",
        "    + 8 * x[25] * x[26] * x[27]\n",
        "    - 8 * x[25] * x[26]\n",
        "    - 4 * x[25] * x[27]\n",
        "    + 8 * x[25] * x[37] * x[45]\n",
        "    - 8 * x[25] * x[37]\n",
        "    - 4 * x[25] * x[45]\n",
        "    + 14 * x[25]\n",
        "    - 8 * x[26] * x[27]\n",
        "    + 4 * x[26]\n",
        "    + 8 * x[27] * x[28] * x[29]\n",
        "    - 4 * x[27] * x[29]\n",
        "    - 2 * x[27]\n",
        "    - 8 * x[28] * x[29]\n",
        "    - 8 * x[29] * x[30] * x[31]\n",
        "    + 4 * x[29] * x[31]\n",
        "    + 8 * x[29] * x[38] * x[49]\n",
        "    - 8 * x[29] * x[38]\n",
        "    - 4 * x[29] * x[49]\n",
        "    + 6 * x[29]\n",
        "    + 8 * x[30] * x[31]\n",
        "    - 4 * x[30]\n",
        "    - 8 * x[31] * x[32] * x[33]\n",
        "    + 4 * x[31] * x[33]\n",
        "    - 6 * x[31]\n",
        "    + 8 * x[33] * x[34] * x[35]\n",
        "    - 4 * x[33] * x[35]\n",
        "    - 8 * x[33] * x[39] * x[53]\n",
        "    + 8 * x[33] * x[39]\n",
        "    + 4 * x[33] * x[53]\n",
        "    - 6 * x[33]\n",
        "    - 8 * x[34] * x[35]\n",
        "    + 2 * x[35]\n",
        "    + 8 * x[36] * x[41]\n",
        "    - 8 * x[37] * x[45]\n",
        "    + 4 * x[37]\n",
        "    - 8 * x[38] * x[49]\n",
        "    + 4 * x[38]\n",
        "    + 4 * x[40] * x[41]\n",
        "    - 8 * x[41] * x[42] * x[43]\n",
        "    + 4 * x[41] * x[43]\n",
        "    - 8 * x[41]\n",
        "    + 8 * x[42] * x[43]\n",
        "    - 4 * x[42]\n",
        "    - 8 * x[43] * x[44] * x[45]\n",
        "    + 8 * x[43] * x[44]\n",
        "    + 4 * x[43] * x[45]\n",
        "    - 8 * x[43] * x[56] * x[63]\n",
        "    + 4 * x[43] * x[63]\n",
        "    - 6 * x[43]\n",
        "    - 4 * x[44]\n",
        "    - 8 * x[45] * x[46] * x[47]\n",
        "    + 4 * x[45] * x[47]\n",
        "    + 2 * x[45]\n",
        "    + 4 * x[46]\n",
        "    - 8 * x[47] * x[48] * x[49]\n",
        "    + 8 * x[47] * x[48]\n",
        "    + 4 * x[47] * x[49]\n",
        "    - 8 * x[47] * x[57] * x[67]\n",
        "    + 4 * x[47] * x[67]\n",
        "    - 2 * x[47]\n",
        "    - 4 * x[48]\n",
        "    - 8 * x[49] * x[50] * x[51]\n",
        "    + 8 * x[49] * x[50]\n",
        "    + 4 * x[49] * x[51]\n",
        "    - 2 * x[49]\n",
        "    + 8 * x[50] * x[51]\n",
        "    - 8 * x[50]\n",
        "    - 8 * x[51] * x[52] * x[53]\n",
        "    + 8 * x[51] * x[52]\n",
        "    + 4 * x[51] * x[53]\n",
        "    - 8 * x[51] * x[58] * x[71]\n",
        "    + 4 * x[51] * x[71]\n",
        "    - 6 * x[51]\n",
        "    + 8 * x[52] * x[53]\n",
        "    - 8 * x[52]\n",
        "    + 8 * x[53] * x[54] * x[55]\n",
        "    - 8 * x[53] * x[54]\n",
        "    - 4 * x[53] * x[55]\n",
        "    - 2 * x[53]\n",
        "    + 4 * x[54]\n",
        "    - 8 * x[55] * x[59] * x[75]\n",
        "    + 4 * x[55] * x[75]\n",
        "    - 2 * x[55]\n",
        "    + 8 * x[56] * x[63]\n",
        "    + 8 * x[57] * x[67]\n",
        "    - 4 * x[57]\n",
        "    + 8 * x[58] * x[71]\n",
        "    + 8 * x[59] * x[75]\n",
        "    - 4 * x[59]\n",
        "    + 4 * x[60] * x[61]\n",
        "    + 8 * x[61] * x[62] * x[63]\n",
        "    - 4 * x[61] * x[63]\n",
        "    + 8 * x[61] * x[76] * x[81]\n",
        "    - 8 * x[61] * x[76]\n",
        "    - 4 * x[61] * x[81]\n",
        "    - 8 * x[63] * x[64] * x[65]\n",
        "    + 8 * x[63] * x[64]\n",
        "    + 4 * x[63] * x[65]\n",
        "    - 6 * x[63]\n",
        "    + 8 * x[65] * x[66] * x[67]\n",
        "    - 8 * x[65] * x[66]\n",
        "    - 4 * x[65] * x[67]\n",
        "    - 8 * x[65] * x[77] * x[85]\n",
        "    + 4 * x[65] * x[85]\n",
        "    + 2 * x[65]\n",
        "    + 4 * x[66]\n",
        "    - 8 * x[67] * x[68] * x[69]\n",
        "    + 8 * x[67] * x[68]\n",
        "    + 4 * x[67] * x[69]\n",
        "    - 10 * x[67]\n",
        "    + 8 * x[68] * x[69]\n",
        "    - 4 * x[68]\n",
        "    + 8 * x[69] * x[70] * x[71]\n",
        "    - 4 * x[69] * x[71]\n",
        "    - 8 * x[69] * x[78] * x[89]\n",
        "    + 4 * x[69] * x[89]\n",
        "    - 6 * x[69]\n",
        "    + 8 * x[71] * x[72] * x[73]\n",
        "    - 8 * x[71] * x[72]\n",
        "    - 4 * x[71] * x[73]\n",
        "    + 2 * x[71]\n",
        "    - 8 * x[72] * x[73]\n",
        "    + 8 * x[72]\n",
        "    - 8 * x[73] * x[74] * x[75]\n",
        "    + 8 * x[73] * x[74]\n",
        "    + 4 * x[73] * x[75]\n",
        "    - 8 * x[73] * x[79] * x[93]\n",
        "    + 8 * x[73] * x[79]\n",
        "    + 4 * x[73] * x[93]\n",
        "    - 6 * x[73]\n",
        "    + 8 * x[74] * x[75]\n",
        "    - 4 * x[74]\n",
        "    - 10 * x[75]\n",
        "    + 4 * x[76]\n",
        "    + 8 * x[78] * x[89]\n",
        "    - 4 * x[78]\n",
        "    - 4 * x[79]\n",
        "    - 4 * x[80] * x[81]\n",
        "    + 4 * x[80]\n",
        "    - 8 * x[81] * x[82] * x[83]\n",
        "    + 8 * x[81] * x[82]\n",
        "    + 4 * x[81] * x[83]\n",
        "    + 8 * x[82] * x[83]\n",
        "    - 8 * x[82]\n",
        "    - 8 * x[83] * x[84] * x[85]\n",
        "    + 4 * x[83] * x[85]\n",
        "    - 8 * x[83] * x[96] * x[103]\n",
        "    + 4 * x[83] * x[103]\n",
        "    - 2 * x[83]\n",
        "    - 8 * x[85] * x[86] * x[87]\n",
        "    + 8 * x[85] * x[86]\n",
        "    + 4 * x[85] * x[87]\n",
        "    - 6 * x[85]\n",
        "    + 8 * x[86] * x[87]\n",
        "    - 4 * x[86]\n",
        "    - 8 * x[87] * x[88] * x[89]\n",
        "    + 4 * x[87] * x[89]\n",
        "    + 8 * x[87] * x[97] * x[107]\n",
        "    - 8 * x[87] * x[97]\n",
        "    - 4 * x[87] * x[107]\n",
        "    + 2 * x[87]\n",
        "    + 4 * x[88]\n",
        "    - 8 * x[89] * x[90] * x[91]\n",
        "    + 8 * x[89] * x[90]\n",
        "    + 4 * x[89] * x[91]\n",
        "    - 10 * x[89]\n",
        "    + 8 * x[90] * x[91]\n",
        "    - 8 * x[90]\n",
        "    - 8 * x[91] * x[92] * x[93]\n",
        "    + 4 * x[91] * x[93]\n",
        "    - 8 * x[91] * x[98] * x[111]\n",
        "    + 8 * x[91] * x[98]\n",
        "    + 4 * x[91] * x[111]\n",
        "    - 10 * x[91]\n",
        "    + 8 * x[92] * x[93]\n",
        "    - 4 * x[92]\n",
        "    - 8 * x[93] * x[94] * x[95]\n",
        "    + 4 * x[93] * x[95]\n",
        "    - 6 * x[93]\n",
        "    + 8 * x[95] * x[99] * x[115]\n",
        "    - 8 * x[95] * x[99]\n",
        "    - 4 * x[95] * x[115]\n",
        "    + 2 * x[95]\n",
        "    + 4 * x[96]\n",
        "    - 8 * x[97] * x[107]\n",
        "    + 4 * x[97]\n",
        "    - 4 * x[98]\n",
        "    - 8 * x[99] * x[115]\n",
        "    + 4 * x[99]\n",
        "    - 4 * x[100] * x[101]\n",
        "    + 8 * x[101] * x[102] * x[103]\n",
        "    - 8 * x[101] * x[102]\n",
        "    - 4 * x[101] * x[103]\n",
        "    - 8 * x[101] * x[116] * x[121]\n",
        "    + 8 * x[101] * x[116]\n",
        "    + 4 * x[101] * x[121]\n",
        "    + 4 * x[101]\n",
        "    - 8 * x[103] * x[104] * x[105]\n",
        "    + 4 * x[103] * x[105]\n",
        "    + 2 * x[103]\n",
        "    + 8 * x[105] * x[106] * x[107]\n",
        "    - 4 * x[105] * x[107]\n",
        "    - 8 * x[105] * x[117] * x[125]\n",
        "    + 4 * x[105] * x[125]\n",
        "    + 2 * x[105]\n",
        "    - 8 * x[106] * x[107]\n",
        "    + 4 * x[106]\n",
        "    + 8 * x[107] * x[108] * x[109]\n",
        "    - 4 * x[107] * x[109]\n",
        "    + 6 * x[107]\n",
        "    - 4 * x[108]\n",
        "    + 8 * x[109] * x[110] * x[111]\n",
        "    - 4 * x[109] * x[111]\n",
        "    - 8 * x[109] * x[118] * x[129]\n",
        "    + 4 * x[109] * x[129]\n",
        "    + 2 * x[109]\n",
        "    - 8 * x[110] * x[111]\n",
        "    + 4 * x[110]\n",
        "    - 8 * x[111] * x[112] * x[113]\n",
        "    + 8 * x[111] * x[112]\n",
        "    + 4 * x[111] * x[113]\n",
        "    + 2 * x[111]\n",
        "    + 8 * x[112] * x[113]\n",
        "    - 8 * x[112]\n",
        "    - 8 * x[113] * x[114] * x[115]\n",
        "    + 4 * x[113] * x[115]\n",
        "    - 8 * x[113] * x[119] * x[133]\n",
        "    + 4 * x[113] * x[133]\n",
        "    - 2 * x[113]\n",
        "    + 6 * x[115]\n",
        "    - 4 * x[116]\n",
        "    + 4 * x[118]\n",
        "    + 4 * x[119]\n",
        "    + 4 * x[120] * x[121]\n",
        "    - 8 * x[121] * x[122] * x[123]\n",
        "    + 4 * x[121] * x[123]\n",
        "    - 4 * x[121]\n",
        "    + 4 * x[122]\n",
        "    - 8 * x[123] * x[124] * x[125]\n",
        "    + 4 * x[123] * x[125]\n",
        "    - 8 * x[123] * x[136] * x[143]\n",
        "    + 4 * x[123] * x[143]\n",
        "    - 2 * x[123]\n",
        "    + 8 * x[124] * x[125]\n",
        "    - 4 * x[124]\n",
        "    + 8 * x[125] * x[126] * x[127]\n",
        "    - 8 * x[125] * x[126]\n",
        "    - 4 * x[125] * x[127]\n",
        "    + 2 * x[125]\n",
        "    - 8 * x[127] * x[128] * x[129]\n",
        "    + 8 * x[127] * x[128]\n",
        "    + 4 * x[127] * x[129]\n",
        "    + 8 * x[127] * x[137] * x[147]\n",
        "    - 8 * x[127] * x[137]\n",
        "    - 4 * x[127] * x[147]\n",
        "    - 2 * x[127]\n",
        "    + 8 * x[129] * x[130] * x[131]\n",
        "    - 4 * x[129] * x[131]\n",
        "    + 2 * x[129]\n",
        "    - 4 * x[130]\n",
        "    - 8 * x[131] * x[132] * x[133]\n",
        "    + 4 * x[131] * x[133]\n",
        "    - 8 * x[131] * x[138] * x[151]\n",
        "    + 4 * x[131] * x[151]\n",
        "    - 2 * x[131]\n",
        "    + 8 * x[133] * x[134] * x[135]\n",
        "    - 4 * x[133] * x[135]\n",
        "    + 2 * x[133]\n",
        "    - 8 * x[134] * x[135]\n",
        "    + 4 * x[134]\n",
        "    - 8 * x[135] * x[139] * x[155]\n",
        "    + 8 * x[135] * x[139]\n",
        "    + 4 * x[135] * x[155]\n",
        "    + 2 * x[135]\n",
        "    + 8 * x[136] * x[143]\n",
        "    - 4 * x[136]\n",
        "    + 4 * x[138]\n",
        "    + 8 * x[139] * x[155]\n",
        "    - 4 * x[139]\n",
        "    - 4 * x[140] * x[141]\n",
        "    - 8 * x[141] * x[142] * x[143]\n",
        "    + 8 * x[141] * x[142]\n",
        "    + 4 * x[141] * x[143]\n",
        "    + 8 * x[142] * x[143]\n",
        "    - 8 * x[142]\n",
        "    - 8 * x[143] * x[144] * x[145]\n",
        "    + 8 * x[143] * x[144]\n",
        "    + 4 * x[143] * x[145]\n",
        "    - 14 * x[143]\n",
        "    + 8 * x[144] * x[145]\n",
        "    - 8 * x[144]\n",
        "    - 8 * x[145] * x[146] * x[147]\n",
        "    + 8 * x[145] * x[146]\n",
        "    + 4 * x[145] * x[147]\n",
        "    - 6 * x[145]\n",
        "    + 8 * x[146] * x[147]\n",
        "    - 4 * x[146]\n",
        "    - 8 * x[147] * x[148] * x[149]\n",
        "    + 8 * x[147] * x[148]\n",
        "    + 4 * x[147] * x[149]\n",
        "    - 6 * x[147]\n",
        "    - 4 * x[148]\n",
        "    - 8 * x[149] * x[150] * x[151]\n",
        "    + 8 * x[149] * x[150]\n",
        "    + 4 * x[149] * x[151]\n",
        "    - 6 * x[149]\n",
        "    + 8 * x[151] * x[152] * x[153]\n",
        "    - 4 * x[151] * x[153]\n",
        "    + 2 * x[151]\n",
        "    + 8 * x[153] * x[154] * x[155]\n",
        "    - 8 * x[153] * x[154]\n",
        "    - 4 * x[153] * x[155]\n",
        "    + 2 * x[153]\n",
        "    - 8 * x[154] * x[155]\n",
        "    + 4 * x[154]\n",
        "    - 2 * x[155]\n",
        "    + 46,\n",
        "    x,\n",
        "    domain=\"ZZ\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ac6f36e3",
      "metadata": {},
      "source": [
        "<span id=\"step-2-run-the-hybrid-algorithm-using-the-fire-opal-optimization-solver\" />\n",
        "\n",
        "## Schritt 2: Führen Sie den Hybridalgorithmus mit dem Fire Opal Optimization Solver aus\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "13ba6d0c",
      "metadata": {},
      "source": [
        "Verwenden Sie nun die Optimization Solver Qiskit Function, um den Algorithmus auszuführen. Hinter den Kulissen kümmert sich der Optimierungslöser darum, das Problem auf einen hybriden Quantenalgorithmus abzubilden, die Quantenschaltungen mit Fehlerunterdrückung laufen zu lassen und die klassische Optimierung durchzuführen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bd38bb1e",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Authenticate to the Qiskit Functions Catalog\n",
        "catalog = QiskitFunctionsCatalog(\n",
        "    token=token,\n",
        "    instance=instance,\n",
        ")\n",
        "\n",
        "# Load the function\n",
        "solver = catalog.load(\"q-ctrl/optimization-solver\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "12cfe6f5",
      "metadata": {},
      "source": [
        "Vergewissern Sie sich, dass das gewählte Gerät mindestens 156 Qubits hat.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a27adab7",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Specify the target backend name\n",
        "backend_name = \"<CHOOSE_A_BACKEND>\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ffbe9f79",
      "metadata": {},
      "source": [
        "Der Solver akzeptiert eine String-Darstellung der Zielfunktion.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 43,
      "id": "1834cb22",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Convert the objective function to string format\n",
        "spin_glass_poly_as_str = srepr(spin_glass_poly)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "98213fe9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Run the problem\n",
        "spin_glass_job = solver.run(\n",
        "    problem=spin_glass_poly_as_str,\n",
        "    run_options={\"backend_name\": backend_name},\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d25caa83",
      "metadata": {},
      "source": [
        "Sie können die bekannten [Qiskit Serverless-APIs](/docs/guides/serverless) verwenden, um den Status Ihres Qiskit Function-Workloads zu überprüfen:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "77a8ded0",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Get job status\n",
        "spin_glass_job.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7cd96271",
      "metadata": {},
      "source": [
        "Der Solver gibt ein Wörterbuch zurück, das die Lösung und die zugehörigen Metadaten enthält, wie beispielsweise den Bitstring der Lösung, die Anzahl der Iterationen und die Zuordnung der Variablen zum Bitstring. Eine vollständige Beschreibung der Ein- und Ausgänge des Solvers finden Sie in der [Dokumentation](/docs/api/functions/q-ctrl-optimization-solver).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bd8bd878",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Poll for results\n",
        "result = spin_glass_job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 54,
      "id": "2bddbcbc",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Get the final bitstring distribution and set the number of shots\n",
        "distribution = result[\"final_bitstring_distribution\"]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "50b94af2",
      "metadata": {},
      "source": [
        "<span id=\"step-3-evaluate-results\" />\n",
        "\n",
        "## Schritt 3: Ergebnisse auswerten\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f6f6e93a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Minimum ground state energy: -242.0\n"
          ]
        }
      ],
      "source": [
        "# Get the solution ground state energy\n",
        "print(f\"Minimum ground state energy: {result['solution_bitstring_cost']}\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "733431ad",
      "metadata": {},
      "source": [
        "Der Solver fand die richtige Lösung, die mit klassischer Optimierungssoftware validiert wurde. Die Komplexität dieses Problems im Versorgungsbereich erfordert eine fortschrittliche Optimierungssoftware, um es klassisch zu lösen, wie [IBM ILOG CPLEX Optimization Studio (CPLEX)](https://www.ibm.com/products/ilog-cplex-optimization-studio) oder [Gurobi Optimization](https://www.gurobi.com/).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "40406a33",
      "metadata": {},
      "source": [
        "Als visuelle Analyse der Qualität der Ergebnisse können Sie die Ergebnisse durch Berechnung der Kostenwerte aus den Bitstrings und deren Wahrscheinlichkeiten darstellen. Zum Vergleich stellen Sie die Ergebnisse neben einer Verteilung von zufällig ausgewählten Bitstrings dar, was einer klassischen \"Brute-force\"-Lösung entspricht. Wenn der Algorithmus durchweg niedrigere Kosten findet, deutet dies darauf hin, dass der Quantenalgorithmus das Optimierungsproblem effektiv löst.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a481c257",
      "metadata": {},
      "outputs": [],
      "source": [
        "def plot_cost_histogram(\n",
        "    costs, probabilities, distribution, qubit_count, bitstring_cost\n",
        "):\n",
        "    \"\"\"Plots a histogram comparing the cost distributions of\n",
        "    Q-CTRL Solver and random sampling.\"\"\"\n",
        "\n",
        "    # Set figure DPI for higher resolution and font size for labels\n",
        "    plt.rcParams[\"figure.dpi\"] = 300\n",
        "    plt.rcParams.update({\"font.size\": 6})  # Set default font size to 6\n",
        "\n",
        "    # Define labels and colors for the plot\n",
        "    labels = [\"Q-CTRL Solver\", \"Random Sampling\"]\n",
        "    colors = [\"#680CE9\", \"#E04542\"]\n",
        "\n",
        "    # Calculate total shots (total number of bitstrings in the distribution)\n",
        "    shots = sum(distribution.values())\n",
        "\n",
        "    # Generate random bitstrings for comparison (random sampling)\n",
        "    rng = np.random.default_rng(seed=0)\n",
        "    random_array = rng.integers(\n",
        "        0, 2, size=(shots, qubit_count)\n",
        "    )  # Generate random bitstrings (0 or 1 for each qubit)\n",
        "    random_bitstrings = [\"\".join(row.astype(str)) for row in random_array]\n",
        "\n",
        "    # Compute the cost for each random bitstring\n",
        "    random_costs = [bitstring_cost(k) for k in random_bitstrings]\n",
        "\n",
        "    # Set uniform probabilities for the random sampling\n",
        "    random_probabilities = (\n",
        "        np.ones(shape=(shots,)) / shots\n",
        "    )  # Equal probability for each random bitstring\n",
        "\n",
        "    # Find the minimum and maximum costs for binning the histogram\n",
        "    min_cost = np.min(costs)\n",
        "    max_cost = np.max(random_costs)\n",
        "\n",
        "    # Create a histogram plot with a smaller figure size (4x2 inches)\n",
        "    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(4, 2))\n",
        "\n",
        "    # Plot histograms for the Q-CTRL solver and random sampling costs\n",
        "    _, _, _ = ax.hist(\n",
        "        [costs, random_costs],  # Data for the two histograms\n",
        "        np.arange(min_cost, max_cost, 2),  # Bins for the histogram\n",
        "        weights=[\n",
        "            probabilities,\n",
        "            random_probabilities,\n",
        "        ],  # Probabilities for each data set\n",
        "        label=labels,  # Labels for the legend\n",
        "        color=colors,  # Colors for each histogram\n",
        "        histtype=\"stepfilled\",  # Filled step histogram\n",
        "        align=\"mid\",  # Align bars to the bin center\n",
        "        alpha=0.8,  # Transparency\n",
        "    )\n",
        "\n",
        "    # Set the x and y labels for the plot\n",
        "    ax.set_xlabel(\"Cost\")\n",
        "    ax.set_ylabel(\"Probability\")\n",
        "\n",
        "    # Add the legend to the plot\n",
        "    ax.legend()\n",
        "\n",
        "    # Show the plot\n",
        "    plt.show()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 59,
      "id": "a2fe3966",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/solve-higher-order-binary-optimization-problems-with-q-ctrls-optimization-solver/extracted-outputs/a2fe3966-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Convert spin_glass_poly into a NumPy-compatible function\n",
        "poly_as_numpy_function = lambdify(x, spin_glass_poly.as_expr(), \"numpy\")\n",
        "\n",
        "\n",
        "# Function to compute the cost of a given bitstring using spin_glass_poly\n",
        "def bitstring_cost(bitstring: str) -> float:\n",
        "    # Convert bitstring to a reversed list of integers (0s and 1s)\n",
        "    return float(\n",
        "        poly_as_numpy_function(*[int(b) for b in str(bitstring[::-1])])\n",
        "    )\n",
        "\n",
        "\n",
        "# Calculate the cost of each bitstring in the distribution\n",
        "costs = [bitstring_cost(k) for k, _ in distribution.items()]\n",
        "\n",
        "# Extract probabilities from the bitstring distribution\n",
        "probabilities = np.array([v for _, v in distribution.items()])\n",
        "probabilities = probabilities / sum(\n",
        "    probabilities\n",
        ")  # Normalize to get probabilities\n",
        "\n",
        "plot_cost_histogram(\n",
        "    costs, probabilities, distribution, qubit_count, bitstring_cost\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "15e35cff",
      "metadata": {},
      "source": [
        "Da das Ziel dieses Optimierungsalgorithmus darin besteht, den minimalen Grundzustand des Ising-Modells zu finden, weisen niedrigere Werte auf bessere Lösungen hin. Daher ist es visuell ersichtlich, dass die vom Fire Opal Optimization Solver generierten Lösungen die Zufallsauswahl bei weitem übertreffen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "hours": 1,
    "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"
    },
    "qpuSeconds": 1440
  },
  "nbformat": 4,
  "nbformat_minor": 5
}