{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "11ea9666",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Optimization Solver - Une fonction Qiskit par Q-CTRL Fire Opal\"\n",
        "description: \"Commencez à résoudre des problèmes d'optimisation à l'échelle des services publics avec le solveur d'optimisation Fire Opal de Q-CTRL\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Sachdeva */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dde95705",
      "metadata": {},
      "source": [
        "<span id=\"optimization-solver-a-qiskit-function-by-q-ctrl-fire-opal\" />\n",
        "\n",
        "# Optimization Solver : une fonction Qiskit par Q-CTRL Fire Opal\n",
        "\n",
        "*Consultez la [documentation de l'API](/docs/api/functions/q-ctrl-optimization-solver)*\n",
        "\n",
        "<Admonition type=\"note\">\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"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "40c2085c",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Versions de package\">\n",
        "    Le code présenté sur cette page a été développé en respectant les exigences suivantes.\n",
        "    Nous vous recommandons d'utiliser ces versions ou des versions plus récentes.\n",
        "\n",
        "    ```\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    sympy~=1.14.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e30c7881",
      "metadata": {},
      "source": [
        "<span id=\"overview\" />\n",
        "\n",
        "## Aperçu\n",
        "\n",
        "Avec le solveur d'optimisation Fire Opal, vous pouvez résoudre des problèmes d'optimisation à grande échelle sur du matériel quantique sans avoir besoin d'expertise quantique. Il suffit de saisir la définition du problème de haut niveau, et le Solveur s'occupe du reste. L'ensemble du flux de travail est sensible au bruit et tire parti de la [gestion des performances de Fire Opal](/docs/guides/q-ctrl-performance-management). Le Solveur fournit systématiquement des solutions précises à des problèmes classiques, même à l'échelle d'un appareil complet sur les plus grandes QPU IBM®.\n",
        "\n",
        "Le solveur est polyvalent et peut être utilisé pour résoudre des problèmes d'optimisation combinatoire définis sous forme de fonctions objectif ou de graphes arbitraires. Il n'est pas nécessaire de faire correspondre les problèmes à la topologie du dispositif. On peut résoudre aussi bien les problèmes sans contraintes que ceux avec contraintes, à condition que ces dernières puissent être formulées sous forme de termes de pénalité. Les exemples présentés dans ce guide montrent comment résoudre un problème d'optimisation à grande échelle, avec ou sans contraintes, en utilisant différents types de données d'entrée pour le solveur. Le premier exemple porte sur un problème de coupe maximale défini sur un graphe régulier de degré 3 comptant 156 nœuds, tandis que le second exemple traite d'un problème de couverture minimale des sommets défini par une fonction de coût et portant sur un graphe de 50 nœuds.\n",
        "\n",
        "Pour obtenir l'accès au solveur d'optimisation, [contactez Q-CTRL](https://form.typeform.com/to/uOAVDnGg?typeform-source=q-ctrl.com).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f761442",
      "metadata": {},
      "source": [
        "<span id=\"function-description\" />\n",
        "\n",
        "## Description de la fonction\n",
        "\n",
        "Le Solver optimise et automatise entièrement l'algorithme, de la suppression des erreurs au niveau matériel à la cartographie efficace des problèmes et à l'optimisation classique en boucle fermée. En coulisses, le pipeline du Solveur réduit les erreurs à chaque étape, ce qui permet d'améliorer les performances requises pour une mise à l'échelle significative. Le processus sous-jacent s'inspire de l'algorithme d'optimisation approximative quantique (QAOA), qui est un algorithme hybride quantique-classique. Pour un résumé détaillé du flux de travail complet d'Optimization Solver, veuillez vous référer au [manuscrit publié.](https://arxiv.org/abs/2406.01743)\n",
        "\n",
        "![Visualisation du flux de travail du solveur d'optimisation](https://quantum.cloud.ibm.com/docs/images/guides/qctrl-optimization/solver_workflow.svg)\n",
        "\n",
        "Pour résoudre un problème générique avec le solveur d'optimisation :\n",
        "\n",
        "1. Définissez votre problème sous la forme d'une fonction objective, d'un graphique ou d'une chaîne de spin ( `SparsePauliOp` ).\n",
        "2. Connectez-vous à la fonction via le catalogue de fonctions Qiskit.\n",
        "3. Exécutez le problème avec le Solveur et récupérez les résultats.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d20af236",
      "metadata": {},
      "source": [
        "<span id=\"accepted-problem-formats\" />\n",
        "\n",
        "### Formats de problèmes acceptés\n",
        "\n",
        "* Représentation de l'expression polynomiale d'une fonction objective. Idéalement créé dans Python avec un objet Poly existant SymPy et formaté dans une chaîne de caractères à l'aide de [sympy.srepr](https://docs.sympy.org/latest/tutorials/intro-tutorial/printing.html#srepr).\n",
        "* Représentation graphique d'un type de problème spécifique. Le graphique doit être créé à l'aide de la bibliothèque networkx dans Python. Il doit ensuite être converti en chaîne de caractères à l'aide de la fonction networkx `[nx.readwrite.json_graph.adjacency_data](http://nx.readwrite.json_graph.adjacency_data.)`.\n",
        "* Représentation en chaîne d'un problème spécifique. La chaîne de spin doit être représentée sous la forme d'un objet `SparsePauliOp` ; voir la [documentation](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp) pour plus de détails.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Cette fonction prend-elle en charge tous les backends d' IBM?\">\n",
        "  Si vous souhaitez utiliser un backend qui n'est pas encore pris en charge par cette fonction, [contactez Q-CTRL](https://form.typeform.com/to/iuujEAEI?typeform-source=q-ctrl.com) pour qu'il soit ajouté.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1165f4f0",
      "metadata": {},
      "source": [
        "<span id=\"benchmarks\" />\n",
        "\n",
        "## Tests de performances\n",
        "\n",
        "[Les résultats d'étalonnage publiés](https://arxiv.org/abs/2406.01743) montrent que le Solver résout avec succès des problèmes avec plus de 120 qubits, surpassant même les résultats précédemment publiés sur le recuit quantique et les dispositifs à ions piégés. Les mesures de référence suivantes donnent une indication approximative de la précision et de l'étendue des types de problèmes sur la base de quelques exemples. Les mesures réelles peuvent différer en fonction de diverses caractéristiques du problème, telles que le nombre de termes dans la fonction objective (densité) et leur localisation, le nombre de variables et l'ordre polynomial.\n",
        "\n",
        "Le \"nombre de qubits\" indiqué n'est pas une limite absolue, mais représente des seuils approximatifs pour lesquels on peut s'attendre à une précision extrêmement constante des solutions. Des problèmes de plus grande taille ont été résolus avec succès, et les essais au-delà de ces limites sont encouragés.\n",
        "\n",
        "La connectivité arbitraire des qubits est prise en charge pour tous les types de problèmes.\n",
        "\n",
        "| Type de problème                            | Nombre de qubits | Exemple                                                                  | Exactitude | Durée totale (s) | Utilisation du temps d'exécution (s) | Nombre d'itérations |\n",
        "| ------------------------------------------- | ---------------- | ------------------------------------------------------------------------ | ---------- | ---------------- | ------------------------------------ | ------------------- |\n",
        "| Problèmes quadratiques à connexions éparses | 156              | 3-régulier max-cut                                                       | 100 %      | 1764             | 293                                  | 16                  |\n",
        "| Optimisation binaire d'ordre supérieur      | 156              | Modèle de verre de spin d'Ising                                          | 100 %      | 1461             | 272                                  | 16                  |\n",
        "| Problèmes quadratiques densément connectés  | 50               | Max-Cut entièrement connecté                                             | 100 %      | 1758             | 268                                  | 12                  |\n",
        "| Problème contraint avec termes de pénalité  | 50               | Couverture minimale pondérée des sommets avec une densité d'arêtes de 8% | 100 %      | 1074             | 215                                  | 10                  |\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73390a19",
      "metadata": {},
      "source": [
        "<span id=\"get-started\" />\n",
        "\n",
        "## Premiers pas\n",
        "\n",
        "Commencez par vous authentifier à l'aide de votre [clé API IBM Quantum](http://quantum.cloud.ibm.com/). Ensuite, sélectionnez la fonction Qiskit comme suit. (Cet extrait de code part du principe que vous avez déjà [enregistré votre compte](/docs/guides/functions-get-started#install-qiskit-functions-catalog-client) dans votre environnement local.)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "95a715d2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[QiskitFunction(qunova/hivqe-chemistry),\n",
              " QiskitFunction(global-data-quantum/quantum-portfolio-optimizer),\n",
              " QiskitFunction(algorithmiq/tem),\n",
              " QiskitFunction(qedma/qesem),\n",
              " QiskitFunction(multiverse/singularity),\n",
              " QiskitFunction(ibm/circuit-function),\n",
              " QiskitFunction(q-ctrl/optimization-solver),\n",
              " QiskitFunction(colibritd/quick-pde),\n",
              " QiskitFunction(q-ctrl/performance-management),\n",
              " QiskitFunction(kipu-quantum/iskay-quantum-optimizer)]"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "catalog = QiskitFunctionsCatalog(channel=\"ibm_quantum_platform\")\n",
        "\n",
        "# Verify that you have access to the function\n",
        "catalog.list()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "8acf84f6",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Access Function\n",
        "solver = catalog.load(\"q-ctrl/optimization-solver\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e8837f5f",
      "metadata": {},
      "source": [
        "<span id=\"example-unconstrained-optimization\" />\n",
        "\n",
        "## Exemple : optimisation sans contrainte\n",
        "\n",
        "Résolvez le problème de [la coupe maximale](https://en.wikipedia.org/wiki/Maximum_cut) (max-cut). L'exemple suivant illustre les capacités du Solveur sur un problème de coupe maximale dans un graphe non pondéré à 3 arêtes régulières et 156 nœuds, mais vous pouvez également résoudre des problèmes sur des graphes pondérés.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a699235b",
      "metadata": {},
      "source": [
        "En plus de `qiskit-ibm-catalog`, vous utiliserez également les paquets suivants pour exécuter cet exemple : `networkx` et `numpy`. Vous pouvez installer ces paquets en décommentant la cellule suivante si vous exécutez cet exemple dans un ordinateur portable utilisant le noyau IPython.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "a74fe6a9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# %pip install networkx numpy"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a41c4a0d",
      "metadata": {},
      "source": [
        "<span id=\"1-define-the-problem\" />\n",
        "\n",
        "### 1. Définir le problème\n",
        "\n",
        "Vous pouvez résoudre un problème de coupe maximale en définissant un problème de graphe et en spécifiant `problem_type='maxcut'`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "d56e1440",
      "metadata": {},
      "outputs": [],
      "source": [
        "import networkx as nx\n",
        "import numpy as np\n",
        "\n",
        "# Generate a random graph with 156 nodes\n",
        "maxcut_graph = nx.random_regular_graph(d=3, n=156, seed=8)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "0a7255e1",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/q-ctrl-optimization-solver/extracted-outputs/0a7255e1-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Optionally, visualize the graph\n",
        "nx.draw_networkx(\n",
        "    maxcut_graph, nx.kamada_kawai_layout(maxcut_graph), node_size=100\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e42a8d55",
      "metadata": {},
      "source": [
        "Le Solveur accepte une chaîne de caractères comme entrée de la définition du problème.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "2546e3e5",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Convert graph to string\n",
        "problem_as_str = nx.readwrite.json_graph.adjacency_data(maxcut_graph)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0ab6f24f",
      "metadata": {},
      "source": [
        "<span id=\"2-run-the-problem\" />\n",
        "\n",
        "### 2. Exécutez le problème\n",
        "\n",
        "Lors de l'utilisation de la méthode de saisie basée sur un graphique, spécifiez le type de problème.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "16c66d64",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Solve the problem\n",
        "maxcut_job = solver.run(\n",
        "    problem=problem_as_str,\n",
        "    problem_type=\"maxcut\",\n",
        "    backend_name=backend_name,  # E.g. \"ibm_fez\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "48069093",
      "metadata": {},
      "source": [
        "Pour vérifier [l'état](/docs/guides/functions-get-started#check-job-status) de votre charge de travail Qiskit Function ou obtenir [les résultats, procédez](/docs/guides/functions-get-started#retrieve-results) comme suit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "856fe992",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "34b53970-d95a-4e24-8763-fc6f3d112843\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QUEUED\n"
          ]
        }
      ],
      "source": [
        "# Print the ID so you can use it later, if necessary\n",
        "print(maxcut_job.job_id)\n",
        "\n",
        "# Get job status\n",
        "print(maxcut_job.status())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "74f48eab",
      "metadata": {},
      "source": [
        "<span id=\"3-retrieve-the-result\" />\n",
        "\n",
        "### 3. Récupérer le résultat\n",
        "\n",
        "Récupérer la valeur de coupe optimale dans le dictionnaire des résultats.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Le mappage des variables vers la chaîne de bits peut avoir changé. Le dictionnaire de sortie contient un `variables_to_bitstring_index_map` sous-dictionnaire qui aide à vérifier l'ordre.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "6b571411",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Optimal cut value: 210.0\n"
          ]
        }
      ],
      "source": [
        "# Poll for results\n",
        "maxcut_result = maxcut_job.result()\n",
        "\n",
        "# Take the absolute value of the solution since the cost function is minimized\n",
        "qctrl_maxcut = abs(maxcut_result[\"solution_bitstring_cost\"])\n",
        "\n",
        "# Print the optimal cut value found by the Optimization Solver\n",
        "print(f\"Optimal cut value: {qctrl_maxcut}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "508e29b0",
      "metadata": {},
      "source": [
        "Vous pouvez vérifier l'exactitude du résultat en résolvant le problème de manière classique avec des solveurs open-source tels que [PuLP](https://coin-or.github.io/pulp/) si le graphe n'est pas densément connecté. Les problèmes de haute densité peuvent nécessiter des solveurs classiques avancés pour valider la solution.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e2817b13",
      "metadata": {},
      "source": [
        "<span id=\"example-constrained-optimization\" />\n",
        "\n",
        "## Exemple : optimisation sous contraintes\n",
        "\n",
        "L'exemple précédent de « max-cut » est un problème courant d'optimisation binaire quadratique sans contraintes. Le solveur d'optimisation de Q-CTRL peut être utilisé pour divers types de problèmes, y compris l'optimisation sous contraintes. Vous pouvez résoudre des problèmes de nature quelconque en saisissant la formulation du problème sous forme de polynôme, dans lequel les contraintes sont modélisées sous forme de termes de pénalité.\n",
        "\n",
        "L'exemple suivant montre comment construire une fonction de coût pour un problème d'optimisation avec contraintes, la [couverture minimale des sommets](https://en.wikipedia.org/wiki/Vertex_cover) (MVC).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a9fbc0e9",
      "metadata": {},
      "source": [
        "En plus des paquets `qiskit-ibm-catalog` et `qiskit` , vous utiliserez également les paquets suivants pour exécuter cet exemple : `numpy`, `networkx`, et `sympy`. Vous pouvez installer ces paquets en décommentant la cellule suivante si vous exécutez cet exemple dans un ordinateur portable utilisant le noyau IPython.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "c6428fd0",
      "metadata": {},
      "outputs": [],
      "source": [
        "# %pip install numpy networkx sympy"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "98d3bfd3",
      "metadata": {},
      "source": [
        "<span id=\"1-define-the-problem\" />\n",
        "\n",
        "### 1. Définir le problème\n",
        "\n",
        "Définir un problème MVC aléatoire en générant un graphe dont les nœuds sont pondérés de manière aléatoire.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "c2ce65e3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/q-ctrl-optimization-solver/extracted-outputs/c2ce65e3-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import networkx as nx\n",
        "from sympy import symbols, Poly, srepr\n",
        "\n",
        "# To change the weights, change the seed to any integer.\n",
        "rng_seed = 18\n",
        "_rng = np.random.default_rng(rng_seed)\n",
        "node_count = 50\n",
        "edge_probability = 0.08\n",
        "mvc_graph = nx.erdos_renyi_graph(\n",
        "    node_count, edge_probability, seed=rng_seed, directed=False\n",
        ")\n",
        "\n",
        "# add node weights\n",
        "for i in mvc_graph.nodes:\n",
        "    mvc_graph.add_node(i, weight=_rng.random())\n",
        "\n",
        "# Optionally, visualize the graph\n",
        "nx.draw_networkx(mvc_graph, nx.kamada_kawai_layout(mvc_graph), node_size=200)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "89c91472",
      "metadata": {},
      "source": [
        "Un modèle d'optimisation standard pour le MVC pondéré peut être formulé comme suit. Tout d'abord, une pénalité doit être ajoutée dans tous les cas où une arête n'est pas connectée à un sommet du sous-ensemble. Par conséquent, laissez $n_i = 1$ si le sommet $i$ est dans la couverture (c'est-à-dire dans le sous-ensemble) et $n_i = 0$ dans le cas contraire. Deuxièmement, l'objectif est de minimiser le nombre total de sommets dans le sous-ensemble, ce qui peut être représenté par la fonction suivante :\n",
        "\n",
        "$\\textbf{Minimize}\\qquad y = \\sum_{i\\in V} \\omega_i n_i$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "91586ee9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Construct the cost function.\n",
        "variables = symbols([f\"n[{i}]\" for i in range(node_count)])\n",
        "cost_function = Poly(0, variables)\n",
        "\n",
        "for i in mvc_graph.nodes():\n",
        "    weight = mvc_graph.nodes[i].get(\"weight\", 0)\n",
        "    cost_function += variables[i] * weight"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9d01684b",
      "metadata": {},
      "source": [
        "Maintenant, chaque arête du graphique doit inclure au moins un point d'extrémité de la couverture, ce qui peut être exprimé par l'inégalité :\n",
        "\n",
        "$n_i + n_j \\ge 1 \\texttt{ for all } (i,j)\\in E$\n",
        "\n",
        "Tous les cas où une arête n'est pas connectée au sommet de couverture doivent être pénalisés. Cela peut être représenté dans la fonction de coût par l'ajout d'une pénalité de la forme $P(1-n_i-n_j+n_i n_j)$ où $P$ est une constante de pénalité positive. Ainsi, une alternative non contrainte à l'inégalité contrainte pour la CVM pondérée est :\n",
        "\n",
        "$\\textbf{Minimize}\\qquad y = \\sum_{i\\in V}\\omega_i n_i + P(\\sum_{(i,j)\\in E}(1 - n_i - n_j + n_i n_j))$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "1ff1ffcc",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Add penalty term.\n",
        "penalty_constant = 2\n",
        "for i, j in mvc_graph.edges():\n",
        "    cost_function += penalty_constant * (\n",
        "        1 - variables[i] - variables[j] + variables[i] * variables[j]\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9fd0ba9e",
      "metadata": {},
      "source": [
        "<span id=\"2-run-the-problem\" />\n",
        "\n",
        "### 2. Exécutez le problème\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "f380b56d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Solve the problem\n",
        "mvc_job = solver.run(\n",
        "    problem=srepr(cost_function),\n",
        "    backend_name=backend_name,  # E.g. \"ibm_fez\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d154c226",
      "metadata": {},
      "source": [
        "Pour vérifier [l'état](/docs/guides/functions-get-started#check-job-status) de votre charge de travail Qiskit Function ou obtenir [les résultats, procédez](/docs/guides/functions-get-started#retrieve-results) comme suit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "6de77b14",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QUEUED\n"
          ]
        }
      ],
      "source": [
        "print(mvc_job.status())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8a95618e",
      "metadata": {},
      "source": [
        "<span id=\"3-get-the-result\" />\n",
        "\n",
        "### 3. Obtenir le résultat\n",
        "\n",
        "Récupérer la solution et analyser les résultats. Comme ce problème comporte des nœuds pondérés, la solution n'est pas simplement le nombre minimum de nœuds couverts. Au lieu de cela, le coût de la solution représente la somme des poids des sommets inclus dans la couverture des sommets. Il représente le \"coût\" ou le \"poids\" total de la couverture de toutes les arêtes du graphe par les sommets sélectionnés.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "a924bf93",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Solution cost: 10.248198273708624\n"
          ]
        }
      ],
      "source": [
        "mvc_result = mvc_job.result()\n",
        "qctrl_cost = mvc_result[\"solution_bitstring_cost\"]\n",
        "\n",
        "# Print results\n",
        "print(f\"Solution cost: {qctrl_cost}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9ec2e67",
      "metadata": {},
      "source": [
        "<span id=\"get-support\" />\n",
        "\n",
        "## Obtenir de l'aide\n",
        "\n",
        "Pour toute question ou problème, [contactez Q-CTRL](https://form.typeform.com/to/iuujEAEI?typeform-source=q-ctrl.com).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "993aa226c6ec9f5e",
      "metadata": {},
      "source": [
        "<span id=\"changelog\" />\n",
        "\n",
        "## Journal des modifications\n",
        "\n",
        "* 11 février 2026 : Nous prenons désormais en charge `ibm_miami`\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a6a25c8",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommandations\">\n",
        "  * Demander l'accès au [solveur d'optimisation Q-CTRL](/functions?id=q-ctrl-optimization-solver).\n",
        "  * Consultez [la documentation de l'API](/docs/api/functions/q-ctrl-optimization-solver) relative à cette fonction Qiskit.\n",
        "  * Essayez le tutoriel [Résoudre des problèmes d'optimisation binaire d'ordre supérieur avec le solveur d'optimisation de Q-CTRL](/docs/tutorials/solve-higher-order-binary-optimization-problems-with-q-ctrls-optimization-solver).\n",
        "  * Critique [Sachdeva, N., et al. (2024).  L'optimisation quantique à l'aide d'un ordinateur quantique à 127 qubits utilisant un modèle de porte IBM peut surpasser les annealeurs quantiques pour les problèmes d'optimisation binaire non triviaux. arXiv prépublication arXiv:2406.01743](https://arxiv.org/abs/2406.01743).\n",
        "  * Critique [Loco, D., et al. (2026).  Prédiction pratique des sites d'hydratation des poches protéiques pour la découverte de médicaments sur un ordinateur quantique. arXiv prépublication arXiv:2512.08390](https://arxiv.org/abs/2512.08390).\n",
        "  * Consultez l'étude de cas [Mazda](https://q-ctrl.com/case-study/tackling-a-costly-bottleneck-in-automotive-design).\n",
        "  * Consultez l'étude de cas [Network Rail](https://q-ctrl.com/case-study/accelerating-the-schedule-for-quantum-enhanced-rail).\n",
        "  * Examinez l'étude de cas [sur l'armée australienne](https://q-ctrl.com/case-study/improving-army-logistics-with-quantum-computing).\n",
        "  * Consultez l'étude de cas [Transport for New South Wales](https://q-ctrl.com/case-study/delivering-quantum-computing-for-faster-commuting).\n",
        "</Admonition>\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
}