{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b6d1e3ec",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Optimisation binaire de niveau supérieur avec le solveur d'optimisation de Q-CTRL\"\n",
        "description: \"Résolvez un problème d'optimisation quantique à l'échelle industrielle à l'aide du solveur d'optimisation, une fonction Qiskit de 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",
        "# Optimisation binaire de niveau supérieur avec le solveur d'optimisation de Q-CTRL\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a6f69b77",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Remarque\">\n",
        "  Les fonctions Qiskit sont une fonctionnalité expérimentale disponible uniquement pour IBM Quantum® Premium Plan, Flex Plan, et On-Prem (via IBM Quantum Platform API). Elles sont en cours de publication et peuvent être modifiées.\n",
        "</Admonition>\n",
        "\n",
        "*Estimation de l'utilisation : 24 minutes sur un processeur Heron r2. (NOTE : Il s'agit uniquement d'une estimation. Votre durée d'exécution peut varier.)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8bf80006",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## Arrière-plan\n",
        "\n",
        "Ce tutoriel montre comment résoudre un problème d'optimisation binaire d'ordre supérieur (HOBO) à l'aide du [Solveur d'optimisation, une fonction Qiskit de Q-CTRL Fire Opal](/docs/guides/q-ctrl-optimization-solver). L'exemple démontré dans ce tutoriel est un problème d'optimisation conçu pour trouver l'énergie de l'état fondamental d'un modèle d'Ising à 156 qubits à liaisons aléatoires possédant des termes cubiques. Le solveur d'optimisation peut être utilisé pour des problèmes d'optimisation généraux qui peuvent être définis comme une fonction objective.\n",
        "\n",
        "L'optimisation automatise entièrement les étapes de la mise en œuvre matérielle de la résolution des problèmes d'optimisation sur le matériel quantique et, en tirant parti de la [gestion des performances](/docs/guides/q-ctrl-performance-management) pour l'exécution quantique, elle permet d'obtenir des solutions précises à l'échelle de l'utilité. Pour un résumé détaillé du flux de travail complet d'Optimization Solver et des résultats de l'analyse comparative, veuillez vous référer au [manuscrit publié.](https://arxiv.org/abs/2406.01743)\n",
        "\n",
        "Ce tutoriel décrit les étapes suivantes :\n",
        "\n",
        "1. Définir le problème sous la forme d'une fonction objective\n",
        "2. Exécuter l'algorithme hybride à l'aide du solveur d'optimisation Fire Opal\n",
        "3. Évaluer les résultats\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "55b94021",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## Exigences\n",
        "\n",
        "Avant de commencer ce tutoriel, assurez-vous que les éléments suivants sont installés :\n",
        "\n",
        "* Fonctions Qiskit (`pip install qiskit-ibm-catalog`)\n",
        "* SymPy (`pip install sympy`)\n",
        "\n",
        "Vous devrez également avoir accès à la fonction Optimization Solver. [Remplissez le formulaire](/functions?id=q-ctrl-optimization-solver) pour demander l'accès.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "7db2e559",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Configuration\n",
        "\n",
        "Tout d'abord, il faut importer les paquets et les outils nécessaires.\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": [
        "Définissez vos identifiants « [IBM Quantum Platform](/) », qui seront utilisés tout au long du tutoriel pour vous authentifier auprès de IBM Quantum Compute Service et Qiskit Functions.\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",
        "## Étape 1 : Définir le problème comme une fonction objective\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6c9bffae",
      "metadata": {},
      "source": [
        "Le solveur d'optimisation accepte en entrée une fonction objective ou un graphique. Dans ce tutoriel, le problème de minimisation du verre de spin d'Ising est défini comme une fonction objective, et il a été adapté à la topologie lourde-hex des dispositifs IBM®.\n",
        "\n",
        "Comme cette fonction objective contient des termes cubiques, quadratiques et linéaires, elle appartient à la classe des problèmes HOBO, connus pour être considérablement plus compliqués à résoudre que les problèmes classiques d'optimisation binaire quadratique sans contrainte (QUBO).\n",
        "\n",
        "Pour une discussion détaillée de la construction de la définition du problème et des résultats précédents obtenus avec le solveur d'optimisation, veuillez vous référer à [ce manuscrit technique.](https://arxiv.org/abs/2406.01743) Le problème a été défini et évalué à l'origine dans le cadre d'un [article publié par le Los Alamos National Laboratory](https://arxiv.org/abs/2312.00997), et il a été adapté pour exploiter toute la largeur du dispositif des processeurs Quantum Heron à 156 qubits IBM.\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",
        "## Étape 2 : Exécutez l'algorithme hybride à l'aide du solveur d'optimisation Fire Opal\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "13ba6d0c",
      "metadata": {},
      "source": [
        "Utilisez maintenant la fonction Qiskit du solveur d'optimisation pour exécuter l'algorithme. En coulisses, le solveur d'optimisation se charge de transposer le problème dans un algorithme quantique hybride, d'exécuter les circuits quantiques avec suppression des erreurs et d'effectuer l'optimisation classique.\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": [
        "Vérifiez que le dispositif choisi possède au moins 156 qubits.\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": [
        "Le solveur accepte une représentation sous forme de chaîne de la fonction objective.\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": [
        "Vous pouvez utiliser les [API sans serveur Qiskit](/docs/guides/serverless) familières pour vérifier l'état de votre charge de travail de fonction Qiskit :\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": [
        "Le solveur renvoie un dictionnaire contenant la solution et les métadonnées associées, telles que la chaîne de bits de la solution, le nombre d'itérations et la correspondance entre les variables et la chaîne de bits. Pour une définition complète des entrées et sorties du Solveur, consultez la [documentation]().\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",
        "## Étape 3 : Évaluer les résultats\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "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": [
        "Le solveur a trouvé la bonne solution, qui a été validée à l'aide d'un logiciel d'optimisation classique. La complexité de ce problème nécessite un logiciel d'optimisation avancé pour être résolu de manière classique, tel que [IBM ILOG CPLEX Optimization Studio (CPLEX)](https://www.ibm.com/products/ilog-cplex-optimization-studio) ou [Gurobi Optimization](https://www.gurobi.com/).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "40406a33",
      "metadata": {},
      "source": [
        "Pour une analyse visuelle de la qualité des résultats, vous pouvez tracer les résultats en calculant les valeurs de coût à partir des chaînes de bits et de leurs probabilités. À titre de comparaison, nous présentons les résultats avec une distribution de chaînes de bits échantillonnées de manière aléatoire, ce qui équivaut à une solution classique \"par force brute\". Si l'algorithme trouve systématiquement des coûts inférieurs, cela signifie que l'algorithme quantique résout efficacement le problème d'optimisation.\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": [
        "L'objectif de cet algorithme d'optimisation étant de trouver l'état fondamental minimum du modèle d'Ising, des valeurs plus faibles indiquent de meilleures solutions. Par conséquent, il est visuellement évident que les solutions générées par le solveur d'optimisation Fire Opal sont bien plus performantes que la sélection aléatoire.\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"
    },
    "hours": 1,
    "qpuSeconds": 1440
  },
  "nbformat": 4,
  "nbformat_minor": 5
}