{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "6581d769-6f75-4b26-90e3-39c28f22a74c",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Solveur d'équations quantiques variationnelles\"\n",
        "description: \"Cette introduction au VQE couvre ses composants, une mise en œuvre de base, et examine les facteurs qui déterminent son efficacité et son utilité.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore ansä IIIZ IZII IIZI ZIII IZIZ IIZZ ZIIZ IZZI ZZII ZIZI XXYY YYXX ansätze ansatze infty IZZX XIYX ZZXZ ZZZX IIXX IIXZ IZXZ IXXZ XZXZ ZIXZ */}\n",
        "\n",
        "<span id=\"the-variational-quantum-eigensolver-vqe\" />\n",
        "\n",
        "# Le solveur d'équations quantiques variationnelles (VQE)\n",
        "\n",
        "Cette leçon présente le résolveur quantique variationnel, explique son importance en tant qu'algorithme fondamental de l'informatique quantique et explore ses forces et ses faiblesses. La VQE en elle-même, sans méthodes complémentaires, n'est probablement pas suffisante pour les calculs quantiques modernes à l'échelle de l'utilité. Elle est néanmoins importante en tant qu'archétype de méthode hybride classique-quantique et constitue une base importante sur laquelle sont construits de nombreux algorithmes plus avancés.\n",
        "\n",
        "Cette vidéo donne un aperçu de la VQE et des facteurs qui influencent son efficacité. Le texte ci-dessous donne plus de détails et met en œuvre le VQE à l'aide de Qiskit.\n",
        "\n",
        "<IBMVideo id=\"134325519\" title=\"Dans cette vidéo, Chris Porter décrit les principaux composants du résolveur quantique variationnel. Il s'agit notamment de l'hamiltonien, de l'ansatz, d'un optimiseur classique et d'un estimateur. Il examine également les facteurs qui influencent l'efficacité de la VQE.\" />\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "21115450-3f01-4e19-860d-48e31f401b1f",
      "metadata": {},
      "source": [
        "<span id=\"1-what-is-vqe\" />\n",
        "\n",
        "## 1. Qu'est-ce que le VQE?\n",
        "\n",
        "Le solveur d'équations aux valeurs propres quantique variationnel est un algorithme qui combine l'informatique classique et l'informatique quantique pour accomplir une tâche. Le calcul de la VQE comporte quatre éléments principaux :\n",
        "\n",
        "* **Un opérateur** : Souvent un hamiltonien, que nous appellerons $H$, qui décrit une propriété de votre système que vous souhaitez optimiser. Une autre façon de le dire est de chercher le vecteur propre de cet opérateur qui correspond à la valeur propre minimale. Nous appelons souvent ce vecteur propre l'\"état fondamental\".\n",
        "* **Un \"ansatz\"** (mot allemand signifiant \"approche\") : il s'agit d'un circuit quantique qui prépare un état quantique approchant le vecteur propre recherché. En réalité, l'ansatz est une famille de circuits quantiques, car certaines des portes de l'ansatz sont paramétrées, c'est-à-dire qu'elles sont alimentées par un paramètre que nous pouvons faire varier. Cette famille de circuits quantiques peut préparer une famille d'états quantiques proches de l'état fondamental.\n",
        "* **Un estimateur** : un moyen d'estimer la valeur attendue de l'opérateur $H$ sur l'état quantique variationnel actuel. Parfois, ce qui nous importe vraiment, c'est simplement cette valeur attendue, que l'on appelle une fonction de coût. Parfois, nous nous intéressons à une fonction plus complexe qui peut néanmoins être écrite à partir d'une ou plusieurs valeurs attendues.\n",
        "* **Un optimiseur classique** : un algorithme qui fait varier les paramètres pour tenter de minimiser la fonction de coût.\n",
        "\n",
        "Examinons chacun de ces éléments plus en détail.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7dbd605e-a440-446b-bc05-e2e301796bf2",
      "metadata": {},
      "source": [
        "<span id=\"11-the-operator-hamiltonian\" />\n",
        "\n",
        "### 1.1 L'opérateur (hamiltonien)\n",
        "\n",
        "Au cœur d'un problème VQE se trouve un opérateur qui décrit un système d'intérêt. Nous supposerons ici que la valeur propre la plus basse et le vecteur propre correspondant de cet opérateur sont utiles à des fins scientifiques ou commerciales. Il peut s'agir par exemple d'un hamiltonien chimique décrivant une molécule, de sorte que la valeur propre la plus basse de l'opérateur correspond à l'énergie de l'état fondamental de la molécule, et que l'état propre correspondant décrit la géométrie ou la configuration électronique de la molécule. L'opérateur peut également décrire le coût d'un certain processus à optimiser, et les états propres peuvent correspondre à des itinéraires ou à des pratiques. Dans certains domaines, comme la physique, un \"hamiltonien\" fait presque toujours référence à un opérateur décrivant l'énergie d'un système physique. Mais en informatique quantique, il est courant de voir les opérateurs quantiques qui décrivent un problème commercial ou logistique également appelés \"hamiltoniens\". Nous adopterons cette convention ici.\n",
        "\n",
        "![Une illustration représentant des orbitales atomiques et une autre illustrant un réseau composé de nombreux nœuds reliés entre eux.](https://quantum.cloud.ibm.com/learning/images/courses/quantum-diagonalization-algorithms/vqe/vqe-fig1.avif)\n",
        "\n",
        "La mise en correspondance d'un problème physique ou d'optimisation avec des qubits est généralement une tâche non triviale, mais ces détails ne font pas l'objet de ce cours. Une discussion générale sur la cartographie d'un problème sur un opérateur quantique peut être trouvée dans [L'informatique quantique en pratique](/learning/courses/quantum-computing-in-practice). Un examen plus détaillé de la conversion des problèmes de chimie en opérateurs quantiques est présenté dans Quantum [Chemistry with VQE (Chimie quantique avec VQE](/learning/courses/quantum-chem-with-vqe) ).\n",
        "\n",
        "Pour les besoins de ce cours, nous supposerons que la forme de l'hamiltonien est connue. Par exemple, un hamiltonien pour une molécule d'hydrogène simple (sous certaines hypothèses d'espace actif, et en utilisant le cartographe de Jordan-Wigner) est :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "89b425d8-f54f-4f98-996e-c303f77edb25",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.quantum_info import SparsePauliOp\n",
        "\n",
        "hamiltonian = SparsePauliOp(\n",
        "    [\n",
        "        \"IIII\",\n",
        "        \"IIIZ\",\n",
        "        \"IZII\",\n",
        "        \"IIZI\",\n",
        "        \"ZIII\",\n",
        "        \"IZIZ\",\n",
        "        \"IIZZ\",\n",
        "        \"ZIIZ\",\n",
        "        \"IZZI\",\n",
        "        \"ZZII\",\n",
        "        \"ZIZI\",\n",
        "        \"YYYY\",\n",
        "        \"XXYY\",\n",
        "        \"YYXX\",\n",
        "        \"XXXX\",\n",
        "    ],\n",
        "    coeffs=[\n",
        "        -0.09820182 + 0.0j,\n",
        "        -0.1740751 + 0.0j,\n",
        "        -0.1740751 + 0.0j,\n",
        "        0.2242933 + 0.0j,\n",
        "        0.2242933 + 0.0j,\n",
        "        0.16891402 + 0.0j,\n",
        "        0.1210099 + 0.0j,\n",
        "        0.16631441 + 0.0j,\n",
        "        0.16631441 + 0.0j,\n",
        "        0.1210099 + 0.0j,\n",
        "        0.17504456 + 0.0j,\n",
        "        0.04530451 + 0.0j,\n",
        "        0.04530451 + 0.0j,\n",
        "        0.04530451 + 0.0j,\n",
        "        0.04530451 + 0.0j,\n",
        "    ],\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "14c20ee9-51ad-4cc9-be36-7a33fae6c56a",
      "metadata": {},
      "source": [
        "Notez que dans l'hamiltonien ci-dessus, il y a des termes comme `ZZII` et `YYYY` qui ne sont pas commutés entre eux. En d'autres termes, pour évaluer `ZZII`, nous devrions mesurer l'opérateur Z de Pauli sur le qubit 3 (entre autres mesures). Mais pour évaluer `YYYY`, nous devons mesurer l'opérateur Y de Pauli sur ce même qubit, le qubit 3. Il existe une relation d'incertitude entre les opérateurs Y et Z sur le même qubit; nous ne pouvons pas mesurer ces deux opérateurs en même temps. Nous reviendrons sur ce point plus loin, et en fait tout au long du cours.\n",
        "L'hamiltonien ci-dessus est un opérateur matriciel $16\\times 16$. Il n'est pas difficile de diagonaliser l'opérateur pour trouver sa valeur propre de plus faible énergie.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "9703b61e-ff90-4e94-8999-242d0c6766c0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The ground state energy is  -1.1459778447627311 hartrees\n"
          ]
        }
      ],
      "source": [
        "import numpy as np\n",
        "\n",
        "A = np.array(hamiltonian)\n",
        "eigenvalues, eigenvectors = np.linalg.eigh(A)\n",
        "print(\"The ground state energy is \", min(eigenvalues), \"hartrees\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "01a76c42-29e7-455a-acd6-55490f36121b",
      "metadata": {},
      "source": [
        "Les résolveurs d'équations classiques de force brute ne peuvent pas décrire les énergies ou les géométries de très grands systèmes d'atomes, comme les médicaments ou les protéines. VQE est l'une des premières tentatives d'exploitation de l'informatique quantique pour résoudre ce problème.\n",
        "\n",
        "Dans cette leçon, nous rencontrerons des hamiltoniens beaucoup plus grands que ceux mentionnés ci-dessus. Mais il serait inutile de repousser les limites de ce que VQE peut faire, avant de présenter certains des outils les plus avancés qui peuvent compléter ou remplacer VQE, plus tard dans ce cours.\n",
        "\n",
        "<span id=\"12-ansatz\" />\n",
        "\n",
        "### 1.2 Ansatz\n",
        "\n",
        "Le mot \"ansatz\" signifie \"approche\" en allemand. Le pluriel correct en allemand est \"ansätze\", bien que l'on trouve souvent \"ansatzes\" ou \"ansatze\". Dans le contexte de l'EQV, un ansatz est le circuit quantique que vous utilisez pour créer une fonction d'onde multi-qubit qui se rapproche le plus de l'état fondamental du système que vous étudiez, et qui produit donc la valeur d'espérance la plus faible de votre opérateur. Ce circuit quantique contiendra des paramètres variationnels (souvent rassemblés dans le vecteur de variables $\\vec{\\theta}$ ).\n",
        "\n",
        "![Image d'un circuit quantique comportant des paramètres variationnels désignés par « thêta ».](https://quantum.cloud.ibm.com/learning/images/courses/quantum-diagonalization-algorithms/vqe/vqe-fig2.avif)\n",
        "\n",
        "Un ensemble initial de valeurs $\\vec{\\theta_0}$ des paramètres variationnels est choisi. Nous appellerons l'opération unitaire de l'ansatz sur le circuit $U_{\\text{var}}(\\vec{\\theta_0})$. Par défaut, tous les qubits des ordinateurs quantiques IBM® sont initialisés à l'état $|0\\rangle$. Lorsque le circuit fonctionne, l'état des qubits est le suivant\n",
        "\n",
        "$$\n",
        "|\\psi(\\vec{\\theta_0})\\rangle=U_{\\text{var}}(\\vec{\\theta_0})|0\\rangle^{\\otimes N}\n",
        "$$\n",
        "\n",
        "Si tout ce dont nous avions besoin était l'énergie la plus basse (en utilisant le langage des systèmes physiques), nous pourrions l'estimer en mesurant simplement l'énergie plusieurs fois et en prenant la plus basse. Mais en général, nous voulons aussi la configuration qui produit l'énergie ou la valeur propre la plus basse. L'étape suivante consiste donc à estimer la valeur d'espérance de l'hamiltonien, ce qui est réalisé grâce à des mesures quantiques. Il y a beaucoup de choses qui entrent en ligne de compte. Mais nous pouvons comprendre ce processus qualitativement en notant que la probabilité $P_j$ de mesurer une énergie $E_j$ (toujours en utilisant le langage des systèmes physiques) est liée à la valeur d'espérance par :\n",
        "\n",
        "$$\n",
        "\\langle \\psi(\\vec{\\theta_0}) |H|\\psi (\\vec{\\theta_0}) \\rangle\n",
        "$$\n",
        "\n",
        "La probabilité $P_j$ est également liée au chevauchement entre l'état propre $|\\phi_j\\rangle$ et l'état actuel du système $|\\psi(\\vec{\\theta_0})\\rangle$ :\n",
        "\n",
        "$$\n",
        "P_j=|\\langle \\phi_j|\\psi(\\vec{\\theta_0})\\rangle|^2 = |\\langle \\phi_j|U_{\\text{var}}(\\vec{\\theta_0})|0\\rangle^{\\otimes N}|^2\n",
        "$$\n",
        "\n",
        "Ainsi, en effectuant de nombreuses mesures des opérateurs de Pauli qui composent notre hamiltonien, nous pouvons estimer la valeur espérée de l'hamiltonien dans l'état actuel du système $|\\psi(\\vec{\\theta_0})\\rangle$. L'étape suivante consiste à faire varier les paramètres $\\vec{\\theta}$ et à essayer de s'approcher davantage de l'état d'énergie le plus bas (état fondamental) du système. En raison des paramètres variationnels dans l'ansatz, on l'appelle parfois **forme variationnelle**.\n",
        "\n",
        "Avant de passer à ce processus variationnel, notez qu'il est souvent utile de commencer votre état à partir d'un état de \"bonne supposition\". Il se peut que vous en sachiez suffisamment sur votre système pour faire une meilleure estimation initiale que $|0\\rangle^{\\otimes N}$. Par exemple, il est courant d'initialiser les qubits à l'état Hartree-Fock dans les applications chimiques. Cette hypothèse de départ, qui ne contient aucun paramètre variationnel, est appelée **état de référence**. Appelons le circuit quantique utilisé pour créer l'état de référence $U_{ref}$. Chaque fois qu'il devient important de distinguer l'état de référence du reste de l'ansatz, utilisons : $U_{\\text{ansatz}}(\\vec{\\theta}) =U_{\\text{var}}(\\vec{\\theta})U_{\\text{ref}}.$ De manière équivalente\n",
        "\n",
        "$$\n",
        "\\begin{aligned}\n",
        "|\\psi_{\\text{ref}}\\rangle&=U_{\\text{ref}}|0\\rangle^{\\otimes N}\\\\\n",
        "|\\psi_{\\text{ansatz}}(\\vec{\\theta})\\rangle&=U_{var}(\\vec{\\theta})|\\psi_{\\text{ref}}\\rangle = U_{\\text{var}}(\\vec{\\theta})U_{\\text{ref}}|0\\rangle^{\\otimes N}.\n",
        "\\end{aligned}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b7f66a1f-93cb-47ee-81c3-6fbf62392003",
      "metadata": {},
      "source": [
        "<span id=\"13-estimator\" />\n",
        "\n",
        "### 1.3 estimateur\n",
        "\n",
        "Nous avons besoin d'un moyen d'estimer la valeur d'espérance de notre hamiltonien dans un état variationnel particulier $|\\psi(\\vec{\\theta})\\rangle$. Si nous pouvions mesurer directement l'opérateur entier $H$, il suffirait d'effectuer de nombreuses mesures (disons $N$ ) et de calculer la moyenne des valeurs mesurées :\n",
        "\n",
        "$$\n",
        "\\langle \\psi(\\vec{\\theta})|H|\\psi(\\vec{\\theta})\\rangle _N \\approx \\frac{1}{N}\\sum_{j=1}^N {E_j}\n",
        "$$\n",
        "\n",
        "Ici, le symbole $\\approx$ nous rappelle que cette valeur attendue ne serait précisément correcte que dans la limite de $N\\rightarrow \\infty$. Mais avec des milliers de mesures effectuées sur un circuit, l'erreur d'échantillonnage de la valeur attendue est assez faible. D'autres considérations, telles que le bruit, posent problème pour les calculs très précis.\n",
        "\n",
        "Cependant, il n’est généralement pas possible de mesurer l’ $H$ e en une seule fois. L’ $H$ e peut contenir plusieurs opérateurs de Pauli X, Y et Z non commutatifs. L'hamiltonien doit donc être décomposé en groupes d'opérateurs pouvant être mesurés simultanément; chaque groupe doit être évalué séparément, puis les résultats combinés pour obtenir une valeur d'espérance. Nous y reviendrons plus en détail lors de la prochaine leçon, lorsque nous aborderons la question de la mise à l'échelle des approches classiques et quantiques. Cette complexité des mesures est l'une des raisons pour lesquelles nous avons besoin d'un code très performant pour réaliser ce type d'estimation. Dans cette leçon et par la suite, nous utiliserons l'estimateur primitif « IBM Quantum » à cette fin.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8b68d38e-80ad-4e02-815f-576806ec3e1c",
      "metadata": {},
      "source": [
        "<span id=\"14-classical-optimizers\" />\n",
        "\n",
        "### 1.4 Optimiseurs classiques\n",
        "\n",
        "Un optimiseur classique est un algorithme classique conçu pour trouver les extrema d'une fonction cible (généralement un minimum). Ils parcourent l'espace des paramètres possibles à la recherche d'un ensemble qui minimise une fonction donnée. Elles peuvent être classées en deux grandes catégories : les méthodes basées sur le gradient, qui utilisent les informations relatives au gradient, et les méthodes sans gradient, qui fonctionnent comme des optimiseurs à boîte noire. Le choix d'un optimiseur classique peut avoir un impact significatif sur les performances d'un algorithme, en particulier en présence de bruit dans le matériel quantique. Les optimiseurs les plus populaires dans ce domaine sont Adam, AMSGrad et SPSA, qui ont donné des résultats prometteurs dans les environnements bruyants. Les optimiseurs plus traditionnels comprennent COBYLA et SLSQP.\n",
        "\n",
        "Un processus courant (démontré dans la section 3.3 ) consiste à utiliser l'un de ces algorithmes comme méthode à l'intérieur d'un minimiseur tel que la fonction `minimize` de scipy. Elle prend comme arguments\n",
        "\n",
        "* Une fonction à minimiser. Il s'agit souvent de la valeur énergétique attendue. Mais ces fonctions sont généralement appelées \"fonctions de coût\".\n",
        "* Un ensemble de paramètres à partir desquels la recherche peut commencer. Souvent appelé $x_0$ ou $\\theta_0$.\n",
        "* Arguments, y compris les arguments de la fonction de coût. Dans le cadre de l'informatique quantique avec Qiskit, ces arguments comprendront l'ansatz, l'hamiltonien et la primitive Estimator, qui sera abordée plus en détail dans la sous-section suivante.\n",
        "* Une \"méthode\" de minimisation. Il s'agit de l'algorithme spécifique utilisé pour rechercher l'espace des paramètres. C'est ici que l'on spécifie, par exemple, COBYLA ou SLSQP.\n",
        "* Options. Les options disponibles peuvent varier selon la méthode. Mais un exemple que pratiquement toutes les méthodes incluraient est le nombre maximum d'itérations de l'optimiseur avant de terminer la recherche : 'maxiter'.\n",
        "\n",
        "![Une image représentant une courbe symbolisant l'énergie, avec plusieurs points auxquels la valeur est testée afin de déterminer le minimum.](https://quantum.cloud.ibm.com/learning/images/courses/quantum-diagonalization-algorithms/vqe/vqe-fig3.avif)\n",
        "\n",
        "À chaque étape itérative, la valeur espérée de l'hamiltonien est estimée en effectuant de nombreuses mesures. Cette énergie estimée est renvoyée par la fonction de coût, et le minimiseur met à jour les informations dont il dispose sur le paysage énergétique. Ce que fait exactement l'optimiseur pour choisir l'étape suivante varie d'une méthode à l'autre. Certains utilisent des gradients et sélectionnent la direction de la descente la plus raide. D'autres peuvent prendre en compte le bruit et exiger que le coût diminue dans une large mesure avant d'accepter que l'énergie réelle diminue dans cette direction.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "9e0642f5-8127-4647-b3f2-deceff0651ec",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Example syntax for minimization\n",
        "# from scipy.optimize import minimize\n",
        "# res = minimize(cost_func, x0, args=(ansatz, hamiltonian, estimator), method=\"cobyla\",\n",
        "# options={'maxiter': 200})"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5bbcff76-ea91-4fb6-acca-35e9e6675ed1",
      "metadata": {},
      "source": [
        "<span id=\"15-the-variational-principle\" />\n",
        "\n",
        "### 1.5 Le principe variationnel\n",
        "\n",
        "Dans ce contexte, le principe de variation est très important; il stipule qu'aucune fonction d'onde variationnelle ne peut produire une valeur d'espérance d'énergie (ou de coût) inférieure à celle produite par la fonction d'onde de l'état fondamental. Mathématiquement,\n",
        "\n",
        "$$\n",
        "E_\\text{var}=\\langle \\psi_\\text{var}|H|\\psi_\\text{var}\\rangle \\geq E_\\text{min}=\\langle \\psi_\\text{0}|H|\\psi_\\text{0}\\rangle\n",
        "$$\n",
        "\n",
        "Ceci est facile à vérifier si nous notons que l'ensemble de tous les états propres $\\{|\\psi_0\\rangle, |\\psi_1\\rangle, |\\psi_2\\rangle, ...|\\psi_n \\rangle\\}$ de $H$ forment une base complète pour l'espace de Hilbert. En d'autres termes, tout état, et en particulier $|\\psi_\\text{var}\\rangle$, peut être écrit comme une somme pondérée (normalisée) de ces états propres de $H$ :\n",
        "\n",
        "$$\n",
        "|\\psi_\\text{var}\\rangle=\\sum_{i=0}^n c_i |\\psi_i\\rangle\n",
        "$$\n",
        "\n",
        "où $c_i$ sont des constantes à déterminer et $\\sum_{i=0} |c_i|^2 = 1$. Nous laissons cet exercice au lecteur. Mais notez l'implication : l'état variationnel qui produit la valeur d'espérance de l'énergie la plus basse *est* la meilleure estimation de l'état fondamental réel.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Vérifiez votre compréhension\n",
        "\n",
        "Vérifiez mathématiquement que $E_\\text{var}\\geq E_0$ pour tout état variationnel $|\\psi_\\text{var}\\rangle$.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Réponse\">\n",
        "    En utilisant l'expansion donnée de l'état variationnel en termes d'états propres énergétiques,\n",
        "\n",
        "    $$\n",
        "    |\\psi_\\text{var}\\rangle=\\sum_{i=0}^n c_i |\\psi_i\\rangle,\n",
        "    $$\n",
        "\n",
        "    nous pouvons écrire la valeur espérée de l'énergie variationnelle comme suit\n",
        "\n",
        "    $$\n",
        "    \\begin{aligned}\n",
        "    E_\\text{var}&=\\langle \\psi_\\text{var}|H|\\psi_\\text{var}\\rangle =\\left(\\sum_{i=0}^n c^*_i \\langle \\psi_i|\\right)H\\left(\\sum_{j=0}^n c_j |\\psi_j\\rangle\\right)\\\\\n",
        "    &=\\left(\\sum_{i=0}^n c^*_i \\langle \\psi_i|\\right)\\left(\\sum_{j=0}^n c_j E_j|\\psi_j\\rangle\\right)\\\\\n",
        "    &=\\sum_{i,j=0}^n c^*_i c_j E_j \\langle \\psi_i|\\psi_j\\rangle\\\\\n",
        "    &=\\sum_{i,j=0}^n c^*_i c_j E_j \\delta_{i,j}\\\\\n",
        "    &=\\sum_{i=0}^n |c_i|^2 E_i.\n",
        "    \\end{aligned}\n",
        "    $$\n",
        "\n",
        "    Pour tous les coefficients $0\\leq|c_i|^2\\leq 1$. On peut donc écrire\n",
        "\n",
        "    $$\n",
        "    \\begin{aligned}\n",
        "    E_\\text{var}&=\\sum_{i=0}^n |c_i|^2 E_i\\geq \\sum_{i=0}^n |c_i|^2 E_0 = E_0 \\sum_{i=0}^n |c_i|^2 = E_0(1) \\\\\n",
        "    E_\\text{var}&\\geq E_0\n",
        "    \\end{aligned}\n",
        "    $$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4d14d6df-7320-4f57-bc62-fbee4041957b",
      "metadata": {},
      "source": [
        "<span id=\"2-comparison-with-classical-workflow\" />\n",
        "\n",
        "## 2. Comparaison avec le flux de travail classique\n",
        "\n",
        "Supposons que nous nous intéressons à une matrice de N lignes et N colonnes. Supposons que votre matrice soit si grande qu'une diagonalisation exacte ne soit pas envisageable. Supposons en outre que vous en sachiez suffisamment sur votre problème pour pouvoir émettre quelques hypothèses sur la structure globale de l'état propre cible, et que vous souhaitiez sonder les états similaires à votre hypothèse initiale pour voir si votre coût/énergie peut être encore réduit. Il s'agit d'une approche variationnelle, qui est utilisée lorsque la diagonalisation exacte n'est pas possible.\n",
        "\n",
        "<span id=\"21-classical-workflow\" />\n",
        "\n",
        "### 2.1 Flux de travail classique\n",
        "\n",
        "En utilisant un ordinateur classique, cela fonctionnerait comme suit :\n",
        "\n",
        "* Faites un état supposé, avec quelques paramètres $\\vec{\\theta}_i$ que vous ferez varier : $|\\psi(\\vec{\\theta}_i)\\rangle$. Bien que cette supposition initiale puisse être aléatoire, cela n'est pas conseillé. Nous voulons utiliser la connaissance du problème en question pour adapter notre supposition autant que possible.\n",
        "* Calculer la valeur d'espérance de l'opérateur avec le système dans cet état : $\\langle\\psi(\\vec{\\theta}_i)|H|\\psi(\\vec{\\theta}_i)\\rangle$\n",
        "* Modifier les paramètres variationnels et répéter : $\\vec{\\theta}_i\\rightarrow \\vec{\\theta}_{i+1}$.\n",
        "* Utilisez les informations accumulées sur le paysage des états possibles dans votre sous-espace variationnel pour faire des suppositions de plus en plus précises et vous rapprocher de l'état cible. Le principe variationnel garantit que notre état variationnel ne peut pas produire une valeur propre inférieure à celle de l'état fondamental cible. Ainsi, plus la valeur d'espérance est faible, meilleure est notre approximation de l'état fondamental :\n",
        "\n",
        "$$\n",
        "\\min_{\\vec{\\theta}} \\{ E_{\\text{var},i} = \\langle\\psi(\\vec{\\theta_i})|H|\\psi(\\vec{\\theta_i})\\rangle \\} \\geq E_0\n",
        "$$\n",
        "\n",
        "Examinons la difficulté de chaque étape de cette approche. Le réglage ou la mise à jour des paramètres est facile à calculer; la difficulté réside dans la sélection de paramètres initiaux utiles et physiquement motivés. L'utilisation des informations accumulées lors des itérations précédentes pour mettre à jour les paramètres de manière à s'approcher de l'état fondamental est une tâche non triviale. Mais il existe des algorithmes d'optimisation classiques qui permettent de le faire de manière assez efficace. Cette optimisation classique n'est coûteuse que parce qu'elle peut nécessiter de nombreuses itérations; dans le pire des cas, le nombre d'itérations peut augmenter de façon exponentielle avec N. L'étape la plus coûteuse en termes de calcul est très certainement le calcul de la valeur d'espérance de votre matrice à partir d'un état donné $|\\psi(\\vec{\\theta_i})\\rangle$ : $\\langle\\psi(\\vec{\\theta_i})|H|\\psi(\\vec{\\theta_i})\\rangle.$\n",
        "\n",
        "La matrice $N\\times N$ doit agir sur le vecteur $N$ -élément, ce qui correspond à : $O(N^2)$ opérations de multiplication dans le pire des cas. Cette opération doit être effectuée à chaque itération des paramètres. Pour les matrices de très grande taille, le coût de calcul est élevé.\n",
        "\n",
        "<span id=\"22-quantum-workflow-and-commuting-pauli-groups\" />\n",
        "\n",
        "### 2.2 Flux de travail quantique et groupes de Pauli de commutation\n",
        "\n",
        "Imaginez maintenant que cette partie du calcul soit confiée à un ordinateur quantique. Au lieu de calculer cette valeur d'espérance, vous l'estimez en préparant l'état $|\\psi(\\vec{\\theta_i})\\rangle$ sur l'ordinateur quantique à l'aide de votre ansatz variationnel, puis en effectuant des mesures.\n",
        "\n",
        "Cela peut sembler plus facile que cela ne l'est. $H$ n'est généralement pas facile à mesurer. Par exemple, il pourrait être composé de nombreux opérateurs X, Y et Z de Pauli non commutatifs. Mais $H$ **peut être** écrit comme une combinaison linéaire de termes, $h_\\alpha$, dont chacun est facilement mesurable (par exemple, des opérateurs de Pauli ou des groupes d'opérateurs de Pauli commutés dans le sens du qubit).\n",
        "La valeur espérée de $H$ sur un certain état $|\\Psi\\rangle$ est la somme pondérée des valeurs espérées des termes constitutifs $h_\\alpha$. Cette expression est valable pour n'importe quel état $|\\Psi⟩$, mais nous l'utiliserons spécifiquement avec nos états variationnels $|\\psi(\\theta_i)\\rangle$.\n",
        "\n",
        "$$\n",
        "H = \\sum_{\\alpha = 1}^T{c_\\alpha h_\\alpha}\n",
        "$$\n",
        "\n",
        "où $h_\\alpha$ est une chaîne de Pauli comme `IZZX…XIYX`, ou plusieurs chaînes de ce type qui commutent entre elles. Une description de la valeur d'espérance plus proche des réalités de la mesure sur les ordinateurs quantiques est donc la suivante\n",
        "\n",
        "$$\n",
        "\\langle \\Psi |H|\\Psi \\rangle =\\sum_{\\alpha} c_\\alpha \\langle \\Psi | h_\\alpha|\\Psi \\rangle.\n",
        "$$\n",
        "\n",
        "Et dans le contexte de notre fonction d'onde variationnelle :\n",
        "\n",
        "$$\n",
        "\\langle \\psi(\\vec{\\theta}_i) |H|\\psi(\\vec{\\theta}_i) \\rangle =\\sum_{\\alpha} c_\\alpha \\langle \\psi(\\vec{\\theta}_i) | h_\\alpha|\\psi(\\vec{\\theta}_i) \\rangle\n",
        "$$\n",
        "\n",
        "Chacun des termes $h_\\alpha$ peut être mesuré $M$ fois, ce qui donne des échantillons de mesure $s_{\\alpha j}$ avec $j=1…M$ et renvoie une valeur attendue $\\mu_\\alpha$ et un écart type $\\sigma_\\alpha$. Nous pouvons additionner ces termes et propager les erreurs à travers la somme pour obtenir une valeur d'espérance globale $\\mu$ et un écart type $\\sigma$.\n",
        "\n",
        "$$\n",
        "\\begin{aligned}\n",
        "\\langle \\psi(\\vec{\\theta}_i) |h_\\alpha|\\psi(\\vec{\\theta}_i) \\rangle &\\simeq \\mu _\\alpha \\pm \\frac{\\sigma_\\alpha}{\\sqrt{M}} &\\qquad \\mu_\\alpha &=\\frac{1}{M}\\sum_j s_{\\alpha,j} &\\qquad \\sigma^2_\\alpha &=\\frac{1}{M-1}\\sum_j (s_{\\alpha,j}-\\mu_\\alpha)^2\\\\\n",
        "\n",
        "\\langle \\psi(\\vec{\\theta}_i) |H|\\psi(\\vec{\\theta}_i) \\rangle &\\simeq \\mu  \\pm \\sigma &\\qquad \\mu &= \\sum_\\alpha c_\\alpha \\mu_\\alpha &\\qquad \\sigma^2&=\\sum_\\alpha c^2_\\alpha \\frac{\\sigma^2_\\alpha }{M}\n",
        "\n",
        "\\end{aligned}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ab02194a-bb0e-4bbc-81e1-c5f8f9582d9b",
      "metadata": {},
      "source": [
        "Cela ne nécessite pas de multiplication à grande échelle, ni de processus qui s'échelonne nécessairement comme $N^2$. Au lieu de cela, il faut effectuer de multiples mesures sur l'ordinateur quantique. Si vous n'avez pas besoin d'un grand nombre d'entre eux, cette approche peut s'avérer efficace. C'est la partie quantique de VQE.\n",
        "\n",
        "Mais examinons les raisons pour lesquelles cela pourrait ne pas être efficace. L'une des raisons d'effectuer de nombreuses mesures est de réduire l'incertitude statistique de vos estimations, pour des calculs de très haute précision. Une autre raison est le nombre de cordes de Pauli nécessaires pour couvrir l'ensemble de la matrice. Comme les matrices de Pauli (plus l'identité : X, Y, Z et I) couvrent l'espace de tous les opérateurs d'une dimension donnée, nous avons la garantie de pouvoir écrire la matrice qui nous intéresse comme une somme pondérée d'opérateurs de Pauli, comme nous l'avons fait précédemment.\n",
        "\n",
        "$$\n",
        "H = \\sum_{\\alpha = 1}^T{c_\\alpha h_\\alpha}\n",
        "$$\n",
        "\n",
        "où $h_\\alpha$ est une chaîne de Pauli agissant sur tous les qubits décrivant votre système comme `IZZX…XIYX`, ou plusieurs chaînes de ce type qui commutent entre elles. Rappelons que Qiskit utilise la notation *little endian*, dans laquelle l'opérateur de Pauli $n^\\text{th}$ de la droite agit sur le qubit $n^\\text{th}$. Nous pouvons donc mesurer notre opérateur en mesurant une série d'opérateurs de Pauli.\n",
        "\n",
        "Mais nous ne pouvons pas mesurer tous ces opérateurs de Pauli en même temps. Les opérateurs de Pauli (à l'exception de I) ne commutent pas entre eux s'ils sont associés au même qubit. Par exemple, nous pouvons mesurer `IZIZ` et `ZZXZ` simultanément, car nous pouvons mesurer I et Z simultanément pour le troisième qubit, et nous pouvons connaître I et X simultanément pour le premier qubit. Mais nous ne pouvons pas mesurer `ZZZZ` et `ZZZX` simultanément, car Z et X ne commutent pas, et agissent tous deux sur le qubit de rang 0. Les lecteurs avertis se souviendront peut-être que deux ensembles d'opérateurs de Pauli peuvent commuter en tant qu'ensemble, même si les mesures effectuées sur chaque qubit pris individuellement ne commutent pas. L'estimateur suppose des mesures de Pauli sous forme de produit tensoriel (via des rotations de base), correspondant à des opérateurs de regroupement qui commutent au niveau des qubits. Ainsi, pour estimer simultanément deux chaînes (A et B) d'opérateurs de Pauli à l'aide d'Estimator, les opérateurs de Pauli de chaque qubit dans A et B doivent commuter. Cela signifie que nous ne pouvons pas non plus mesurer `ZZZZ` et `ZZXX` simultanément.\n",
        "\n",
        "![Un tableau présentant différentes cordes de Pauli, dont certaines commutent et d'autres non.](https://quantum.cloud.ibm.com/learning/images/courses/quantum-diagonalization-algorithms/vqe/vqe-fig4.avif)\n",
        "\n",
        "Nous décomposons donc notre matrice $H$ en une somme de Paulis agissant sur différents qubits. Certains éléments de cette somme peuvent être mesurés en une seule fois; nous appelons cela un *groupe de Paulis commutatifs*. En fonction du nombre de mandats non pendulaires, nous pourrions avoir besoin de plusieurs groupes de ce type. Appelons le nombre de ces groupes de cordes de Pauli commutatives $N_\\text{GCP}$. Si $N_\\text{GCP}$ est petit, cela pourrait bien fonctionner. Si $H$ a des millions de groupes, cela ne sera pas utile.\n",
        "\n",
        "Les processus nécessaires au calcul de la valeur attendue sont regroupés dans la primitive « Estimator » de l' IBM Quantum. Pour en savoir plus sur Estimator, consultez la documentation [de référence de l'API](/docs/api/qiskit-ibm-runtime/estimator-v2) dans la documentation d' IBM Quantum®. On peut bien sûr utiliser directement la fonction « Estimator », mais celle-ci renvoie bien plus que la simple valeur propre d'énergie la plus faible. Par exemple, elle renvoie également des informations sur l'erreur-type d'ensemble. Ainsi, dans le cadre des problèmes de minimisation, on retrouve souvent un « estimateur » au sein d'une fonction de coût. Pour en savoir plus sur les données d'entrée et de sortie d'Estimator, consultez ce [guide](/docs/guides/primitive-input-output#pubs) dans la documentation d' IBM Quantum.\n",
        "\n",
        "Vous enregistrez la valeur d'espérance (ou la fonction de coût) pour l'ensemble des paramètres $\\vec{\\theta_i}$ utilisés dans votre État, puis vous mettez à jour les paramètres. Au fil du temps, vous pouvez utiliser les valeurs d'espérance ou les valeurs de la fonction de coût que vous avez estimées pour obtenir une approximation du gradient de votre fonction de coût dans le sous-espace des états échantillonnés par votre ansatz. Il existe des optimiseurs classiques basés sur le gradient et des optimiseurs classiques sans gradient. Tous deux souffrent de problèmes potentiels de formation, tels que de multiples minima locaux et de vastes régions de l'espace des paramètres avec un gradient proche de zéro, appelées *plateaux stériles*.\n",
        "\n",
        "![Deux représentations d'une droite courbe présentant un minimum. Dans l'une, on vérifie aléatoirement des points afin de trouver un minimum; dans l'autre, on estime un gradient en traçant une ligne entre deux points adjacents.](https://quantum.cloud.ibm.com/learning/images/courses/quantum-diagonalization-algorithms/vqe/vqe-fig5.avif)\n",
        "\n",
        "<span id=\"23-factors-that-determine-computational-cost\" />\n",
        "\n",
        "### 2.3 Facteurs qui déterminent le coût de calcul\n",
        "\n",
        "VQE ne résoudra pas tous vos problèmes de chimie quantique les plus difficiles. Non. Mais il ne s'agit pas d'être meilleur dans tous les calculs. Nous avons déplacé ce qui détermine le coût de calcul.\n",
        "\n",
        "![Tableau comparatif des approches variationnelles classiques et quantiques. Dans les deux cas, il faut partir d'hypothèses de départ pertinentes. En théorie classique, le coût est proportionnel au carré de la dimension de votre matrice, tandis que dans l'approche quantique, il dépend du nombre de groupes d'opérateurs de Pauli commutatifs dont vous disposez.](https://quantum.cloud.ibm.com/learning/images/courses/quantum-diagonalization-algorithms/vqe/vqe-fig6.avif)\n",
        "\n",
        "Nous sommes passés d'un processus dont la complexité dépend uniquement de la dimension de la matrice à un processus qui dépend de la précision requise et du nombre d'opérateurs de Pauli non commutatifs qui composent la matrice. Ce dernier point n'a pas d'analogue dans l'informatique classique.\n",
        "\n",
        "Sur la base de ces dépendances, ce processus peut s'avérer utile pour les matrices peu denses ou les matrices comportant peu de chaînes de Pauli non commutatives. C'est le cas des systèmes de spins en interaction, par exemple. Pour les matrices denses, il peut être moins utile. Nous savons par exemple que les systèmes chimiques ont souvent des hamiltoniens qui impliquent des centaines, des milliers, voire des millions de chaînes de Pauli. Des travaux intéressants ont été menés pour réduire ce nombre de termes. Mais les systèmes chimiques peuvent être mieux adaptés à certains des autres algorithmes que nous aborderons dans ce cours.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Vérifiez votre compréhension\n",
        "\n",
        "Considérons un hamiltonien sur quatre qubits qui contient les termes :\n",
        "\n",
        "`IIXX`, `IIXZ`, `IIZZ`, `IZXZ`, `IXXZ`, `ZZXZ`, `XZXZ`, `ZIXZ`, `ZZZZ`, `XXXX`\n",
        "\n",
        "Vous souhaitez classer ces termes en groupes de manière à ce que tous les termes d'un groupe puissent être mesurés simultanément. Quel est le plus petit nombre de groupes de ce type que l'on puisse constituer de manière à ce que tous les termes soient pris en compte?\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Réponse\">\n",
        "    On peut le faire en 4 groupes. Il convient de noter que ces solutions ne sont généralement pas uniques.\n",
        "\n",
        "    `IIXX`, `XXXX`, `IIZZ`, `ZZZZ`\n",
        "\n",
        "    `IIXZ`, `IZXZ`, `ZIXZ`, `ZZXZ`\n",
        "\n",
        "    `IXXZ`\n",
        "\n",
        "    `XZXZ`\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Selon vous, qu'est-ce qui rend généralement difficile la chimie quantique avec la méthode VQE : le nombre de termes dans l'hamiltonien, ou la recherche d'une bonne approximation?\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Réponse\">\n",
        "    Il s'avère qu'il existe des réponses très optimisées pour les contextes chimiques. Le nombre de termes dans l'hamiltonien, et donc le nombre de mesures nécessaires, posent généralement plus de problèmes.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a9a687e3-ae98-49f7-9b5a-0a2700ecd278",
      "metadata": {},
      "source": [
        "<span id=\"3-example-hamiltonian\" />\n",
        "\n",
        "## 3. Exemple d'hamiltonien\n",
        "\n",
        "Mettons cet algorithme en pratique en utilisant une petite matrice hamiltonienne afin de voir ce qui se passe à chaque étape. Nous utiliserons le cadre des modèles Qiskit :\n",
        "\n",
        "* **Étape 1** : Cartographier le problème en circuits et opérateurs quantiques - **Étape 2** : Optimisation pour le matériel cible - **Étape 3** : Exécution sur le matériel cible - **Étape 4** : Post-traitement des résultats\n",
        "\n",
        "<span id=\"31-step-1-map-the-problem-to-quantum-circuits-and-operators\" />\n",
        "\n",
        "### 3.1 Étape 1 : Transposer le problème en circuits quantiques et opérateurs\n",
        "\n",
        "Nous utiliserons celle définie ci-dessus dans le contexte de la chimie. Nous commençons par quelques importations générales.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "acb6fb0c-4b8c-4ab3-b632-ed201e99b45f",
      "metadata": {},
      "outputs": [],
      "source": [
        "# General imports\n",
        "import numpy as np\n",
        "\n",
        "# SciPy minimizer routine\n",
        "from scipy.optimize import minimize\n",
        "\n",
        "# Plotting functions\n",
        "import matplotlib.pyplot as plt"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a713b494-ab7a-49c6-845c-db728c4635eb",
      "metadata": {},
      "source": [
        "Là encore, nous supposons que l'hamiltonien en question est connu. Nous utiliserons ici un hamiltonien extrêmement petit, car les autres méthodes abordées dans ce cours seront plus efficaces pour résoudre des problèmes plus importants.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "0908f251-58af-49f9-98a8-af98110f6c15",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The ground state energy is  -0.702930394459531\n"
          ]
        }
      ],
      "source": [
        "from qiskit.quantum_info import SparsePauliOp\n",
        "import numpy as np\n",
        "\n",
        "hamiltonian = SparsePauliOp.from_list(\n",
        "    [(\"YZ\", 0.3980), (\"ZI\", -0.3980), (\"ZZ\", -0.0113), (\"XX\", 0.1810)]\n",
        ")\n",
        "\n",
        "A = np.array(hamiltonian)\n",
        "eigenvalues, eigenvectors = np.linalg.eigh(A)\n",
        "print(\"The ground state energy is \", min(eigenvalues))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "75bf2097-1a9c-48d5-8eff-393e0c9eb2f9",
      "metadata": {},
      "source": [
        "Il existe de nombreux choix d'ansatz préfabriqués à Qiskit. Nous utiliserons `efficient_su2`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "84d6380e-8ee8-4340-a416-c07900fe4c5b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "This circuit has  4 parameters\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/quantum-diagonalization-algorithms/vqe/extracted-outputs/84d6380e-8ee8-4340-a416-c07900fe4c5b-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Pre-defined ansatz circuit and operator class for Hamiltonian\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "# Note that it is more common to place initial 'h' gates outside the ansatz.\n",
        "# Here we specifically wanted this layer structure.\n",
        "ansatz = efficient_su2(\n",
        "    hamiltonian.num_qubits, su2_gates=[\"h\", \"rz\", \"y\"], entanglement=\"circular\", reps=1\n",
        ")\n",
        "\n",
        "num_params = ansatz.num_parameters\n",
        "print(\"This circuit has \", num_params, \"parameters\")\n",
        "\n",
        "ansatz.decompose().draw(\"mpl\", style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "15394107-6589-4d06-b611-8fa641784b33",
      "metadata": {},
      "source": [
        "Des réponses différentes auront des structures d'enchevêtrement différentes et des portes de rotation différentes. Celle présentée ici utilise des portes CNOT pour l'enchevêtrement, et des portes Y et des portes RZ paramétrées pour les rotations. Notez la taille de cet espace de paramètres; cela signifie que nous devons minimiser la fonction de coût sur 4 variables (les paramètres des portes RZ). Ce système peut être étendu, mais pas indéfiniment. L'exécution d'un problème similaire sur 4 qubits, en utilisant les 3 répétitions par défaut pour `efficient_su2` , donne 16 paramètres variationnels.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "12ee2d18-b4db-4b94-ab19-8a0654ca4b2e",
      "metadata": {},
      "source": [
        "<span id=\"32-step-2-optimize-for-target-hardware\" />\n",
        "\n",
        "### 3.2 Étape 2 : Optimisation pour le matériel cible\n",
        "\n",
        "L'ansatz a été écrit en utilisant des portes familières, mais notre circuit doit être transposé pour utiliser les portes de base qui peuvent être mises en œuvre sur chaque ordinateur quantique. Nous sélectionnons le backend le moins sollicité.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "ba1a1493-e807-44b8-b971-69f098981da2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "<IBMBackend('ibm_torino')>\n"
          ]
        }
      ],
      "source": [
        "# runtime imports\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, Session\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "\n",
        "# To run on hardware, select the backend with the fewest number of jobs in the queue\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "print(backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "84200023-d16f-41d4-9791-c6ef3488da90",
      "metadata": {},
      "source": [
        "Nous pouvons maintenant transpiler notre circuit pour ce matériel et visualiser notre ansatz transpilé.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "4a1cdcf3-7d94-4a1f-b675-9549bf28d956",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/quantum-diagonalization-algorithms/vqe/extracted-outputs/4a1cdcf3-7d94-4a1f-b675-9549bf28d956-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "target = backend.target\n",
        "pm = generate_preset_pass_manager(target=target, optimization_level=3)\n",
        "\n",
        "ansatz_isa = pm.run(ansatz)\n",
        "\n",
        "ansatz_isa.draw(output=\"mpl\", idle_wires=False, style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6066c477-2d43-459f-bfc6-650011279587",
      "metadata": {},
      "source": [
        "Notez que les portes utilisées ont changé et que les qubits de notre circuit abstrait ont été mis en correspondance avec des qubits numérotés différemment sur l'ordinateur quantique. Nous devons cartographier notre hamiltonien de manière identique pour que nos résultats soient significatifs.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "3543e888-6f84-4f12-88a8-948dec7f3f55",
      "metadata": {},
      "outputs": [],
      "source": [
        "hamiltonian_isa = hamiltonian.apply_layout(layout=ansatz_isa.layout)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ba1ae1c5-c26c-42f8-b3af-411970d4d39d",
      "metadata": {},
      "source": [
        "<span id=\"33-step-3-execute-on-target-hardware\" />\n",
        "\n",
        "### 3.3 Étape 3 : Exécuter sur le matériel cible\n",
        "\n",
        "<span id=\"331-reporting-out-values\" />\n",
        "\n",
        "#### 3.3.1 Communication des valeurs\n",
        "\n",
        "Nous définissons ici une fonction de coût qui prend comme arguments les structures que nous avons construites lors des étapes précédentes : les paramètres, l'ansatz et l'hamiltonien. Il utilise également Estimator, que nous n'avons pas encore défini. Nous intégrons du code permettant de suivre l'évolution de notre fonction de coût, afin de pouvoir vérifier son comportement en matière de convergence.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bb1d8999-77aa-4c1a-adae-8974eda9e63b",
      "metadata": {},
      "outputs": [],
      "source": [
        "def cost_func(params, ansatz, hamiltonian, estimator):\n",
        "    \"\"\"Return estimate of energy from Estimator\n",
        "\n",
        "    Parameters:\n",
        "        params (ndarray): Array of ansatz parameters\n",
        "        ansatz (QuantumCircuit): Parameterized ansatz circuit\n",
        "        hamiltonian (SparsePauliOp): Operator representation of Hamiltonian\n",
        "        estimator (EstimatorV2): Estimator primitive instance\n",
        "        cost_history_dict: Dictionary for storing intermediate results\n",
        "\n",
        "    Returns:\n",
        "        float: Energy estimate\n",
        "    \"\"\"\n",
        "    pub = (ansatz, [hamiltonian], [params])\n",
        "    result = estimator.run(pubs=[pub]).result()\n",
        "    energy = result[0].data.evs[0]\n",
        "\n",
        "    cost_history_dict[\"iters\"] += 1\n",
        "    cost_history_dict[\"prev_vector\"] = params\n",
        "    cost_history_dict[\"cost_history\"].append(energy)\n",
        "    print(f\"Iters. done: {cost_history_dict['iters']} [Current cost: {energy}]\")\n",
        "\n",
        "    return energy\n",
        "\n",
        "\n",
        "cost_history_dict = {\n",
        "    \"prev_vector\": None,\n",
        "    \"iters\": 0,\n",
        "    \"cost_history\": [],\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "95537d30-ba5d-48ab-bf6a-82edc8f0a348",
      "metadata": {},
      "source": [
        "Il est très avantageux de pouvoir choisir les valeurs initiales des paramètres en fonction de la connaissance du problème et des caractéristiques de l'état cible. Nous ne ferons aucune hypothèse sur ces connaissances et utiliserons des valeurs initiales aléatoires.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "01a5d370-2947-4441-b71b-ffbdeddf52f0",
      "metadata": {},
      "outputs": [],
      "source": [
        "x0 = 2 * np.pi * np.random.random(num_params)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "8e0d33b8-7f9c-428d-a76d-d832747b8430",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Iters. done: 1 [Current cost: 0.010575798722044727]\n",
            "Iters. done: 2 [Current cost: 0.004040015974440895]\n",
            "Iters. done: 3 [Current cost: 0.0020213258785942503]\n",
            "Iters. done: 4 [Current cost: 0.18723082446726014]\n",
            "Iters. done: 5 [Current cost: -0.2746792152068885]\n",
            "Iters. done: 6 [Current cost: -0.3094547651648519]\n",
            "Iters. done: 7 [Current cost: -0.05281985428356641]\n",
            "Iters. done: 8 [Current cost: 0.00808560303514377]\n",
            "Iters. done: 9 [Current cost: -0.0014821685303514388]\n",
            "Iters. done: 10 [Current cost: -0.004759824281150161]\n",
            "Iters. done: 11 [Current cost: 0.09942328705995292]\n",
            "Iters. done: 12 [Current cost: 0.01092366214057508]\n",
            "Iters. done: 13 [Current cost: 0.05017497496069776]\n",
            "Iters. done: 14 [Current cost: 0.13028868414310696]\n",
            "Iters. done: 15 [Current cost: 0.013747803514376994]\n",
            "Iters. done: 16 [Current cost: 0.2583072432944498]\n",
            "Iters. done: 17 [Current cost: -0.14422125655131562]\n",
            "Iters. done: 18 [Current cost: -0.0004950150347678081]\n",
            "Iters. done: 19 [Current cost: 0.00681082268370607]\n",
            "Iters. done: 20 [Current cost: -0.0023377795527156544]\n",
            "Iters. done: 21 [Current cost: 0.6027665591169237]\n",
            "Iters. done: 22 [Current cost: 0.00596641373801917]\n",
            "Iters. done: 23 [Current cost: -0.008318769968051117]\n",
            "Iters. done: 24 [Current cost: -0.00026683306709265246]\n",
            "Iters. done: 25 [Current cost: -0.007648222843450479]\n",
            "Iters. done: 26 [Current cost: 0.004121086261980831]\n",
            "Iters. done: 27 [Current cost: -0.004075019968051117]\n",
            "Iters. done: 28 [Current cost: -0.004419369009584665]\n",
            "Iters. done: 29 [Current cost: 0.213185460054037]\n",
            "Iters. done: 30 [Current cost: -0.06505919572162797]\n",
            "Iters. done: 31 [Current cost: -0.5334241316590271]\n",
            "Iters. done: 32 [Current cost: 0.00218370607028754]\n",
            "Iters. done: 33 [Current cost: 0.09579352143666908]\n",
            "Iters. done: 34 [Current cost: -0.009274800319488819]\n",
            "Iters. done: 35 [Current cost: -0.44395141360688106]\n",
            "Iters. done: 36 [Current cost: 0.011747104632587858]\n",
            "Iters. done: 37 [Current cost: -0.003344149361022364]\n",
            "Iters. done: 38 [Current cost: 0.19138183916486304]\n",
            "Iters. done: 39 [Current cost: 0.013513931813145209]\n"
          ]
        }
      ],
      "source": [
        "# This required 13 min, 20 s QPU time on an Eagle processor, 28 min total time.\n",
        "with Session(backend=backend) as session:\n",
        "    estimator = Estimator(mode=session)\n",
        "    estimator.options.default_shots = 10000\n",
        "\n",
        "    res = minimize(\n",
        "        cost_func,\n",
        "        x0,\n",
        "        args=(ansatz_isa, hamiltonian_isa, estimator),\n",
        "        method=\"cobyla\",\n",
        "        options={\"maxiter\": 50},\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fe98bde2-b435-47d1-b227-ee897aa3fe3e",
      "metadata": {},
      "source": [
        "Nous pouvons examiner les résultats bruts.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "b1d07809-5f98-4c11-9bf6-fc5b5c5fb47f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              " message: Return from COBYLA because the trust region radius reaches its lower bound.\n",
              " success: True\n",
              "  status: 0\n",
              "     fun: -0.5334241316590271\n",
              "       x: [ 1.024e+00  6.459e+00  3.625e+00  4.007e+00]\n",
              "    nfev: 39\n",
              "   maxcv: 0.0"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "res"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "80c958e5-f70e-4736-889a-f88a69c50890",
      "metadata": {},
      "source": [
        "<span id=\"34-step-4-post-process-results\" />\n",
        "\n",
        "### 3.4 Étape 4 : Post-traitement des résultats\n",
        "\n",
        "Si la procédure se termine correctement, les valeurs de notre dictionnaire doivent être égales au vecteur de solution et au nombre total d'évaluations de la fonction, respectivement. Ceci est facile à vérifier :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "e87046c1-bfe9-4bb3-b7fd-1e4da55149fe",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'prev_vector': array([1.02397956, 6.45886604, 3.62479262, 4.00744128]),\n",
              " 'iters': 39,\n",
              " 'cost_history': [np.float64(0.010575798722044727),\n",
              "  np.float64(0.004040015974440895),\n",
              "  np.float64(0.0020213258785942503),\n",
              "  np.float64(0.18723082446726014),\n",
              "  np.float64(-0.2746792152068885),\n",
              "  np.float64(-0.3094547651648519),\n",
              "  np.float64(-0.05281985428356641),\n",
              "  np.float64(0.00808560303514377),\n",
              "  np.float64(-0.0014821685303514388),\n",
              "  np.float64(-0.004759824281150161),\n",
              "  np.float64(0.09942328705995292),\n",
              "  np.float64(0.01092366214057508),\n",
              "  np.float64(0.05017497496069776),\n",
              "  np.float64(0.13028868414310696),\n",
              "  np.float64(0.013747803514376994),\n",
              "  np.float64(0.2583072432944498),\n",
              "  np.float64(-0.14422125655131562),\n",
              "  np.float64(-0.0004950150347678081),\n",
              "  np.float64(0.00681082268370607),\n",
              "  np.float64(-0.0023377795527156544),\n",
              "  np.float64(0.6027665591169237),\n",
              "  np.float64(0.00596641373801917),\n",
              "  np.float64(-0.008318769968051117),\n",
              "  np.float64(-0.00026683306709265246),\n",
              "  np.float64(-0.007648222843450479),\n",
              "  np.float64(0.004121086261980831),\n",
              "  np.float64(-0.004075019968051117),\n",
              "  np.float64(-0.004419369009584665),\n",
              "  np.float64(0.213185460054037),\n",
              "  np.float64(-0.06505919572162797),\n",
              "  np.float64(-0.5334241316590271),\n",
              "  np.float64(0.00218370607028754),\n",
              "  np.float64(0.09579352143666908),\n",
              "  np.float64(-0.009274800319488819),\n",
              "  np.float64(-0.44395141360688106),\n",
              "  np.float64(0.011747104632587858),\n",
              "  np.float64(-0.003344149361022364),\n",
              "  np.float64(0.19138183916486304),\n",
              "  np.float64(0.013513931813145209)]}"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "cost_history_dict"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "a789373a-8d32-4761-ba21-6b2f98a7ae5a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/quantum-diagonalization-algorithms/vqe/extracted-outputs/a789373a-8d32-4761-ba21-6b2f98a7ae5a-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "fig, ax = plt.subplots()\n",
        "x = np.linspace(0, 10, 50)\n",
        "\n",
        "# Define the constant function\n",
        "constant = -0.7029\n",
        "y_constant = np.full_like(x, constant)\n",
        "ax.plot(\n",
        "    range(cost_history_dict[\"iters\"]), cost_history_dict[\"cost_history\"], label=\"VQE\"\n",
        ")\n",
        "ax.set_xlabel(\"Iterations\")\n",
        "ax.set_ylabel(\"Cost\")\n",
        "ax.plot(y_constant, label=\"Target\")\n",
        "plt.legend()\n",
        "plt.draw()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4be8cb84-ec8c-4c83-880f-b9c296282040",
      "metadata": {},
      "source": [
        "IBM Quantum propose d'autres offres de perfectionnement liées à la VQE. Si vous êtes prêt à mettre VQE en pratique, consultez notre tutoriel : [Estimation de l'énergie de l'état fondamental de la chaîne de Heisenberg avec VQE](/docs/tutorials/spin-chain-vqe). Si vous souhaitez plus d'informations sur la création d'hamiltoniens moléculaires, consultez [cette leçon](/learning/courses/quantum-chem-with-vqe/hamiltonian-construction) dans notre cours sur la [chimie quantique avec VQE](/learning/courses/quantum-chem-with-vqe). Si vous souhaitez mieux comprendre le fonctionnement des algorithmes variationnels tels que VQE, nous vous recommandons le cours [Variational Algorithm Design.](/learning/courses/variational-algorithm-design/optimization-loops)\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Vérifiez votre compréhension\n",
        "\n",
        "Dans cette section, nous avons calculé l'énergie de l'état fondamental à partir d'un hamiltonien. Si nous voulions appliquer ce principe à la détermination de la géométrie d'une molécule, par exemple, comment pourrions-nous l'étendre?\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Réponse\">\n",
        "    Nous devrions introduire des variables pour l'espacement inter-atomique et les angles entre les liaisons. Nous devrions les modifier. Pour chaque variation de ces éléments, nous produirons un nouvel hamiltonien (puisque les opérateurs décrivant l'énergie dépendent certainement de la géométrie). Pour chaque hamiltonien de ce type produit et mis en correspondance avec des qubits, nous devrions procéder à une optimisation comme celle effectuée ci-dessus. Parmi tous ces nombreux problèmes d'optimisation convergents, la géométrie qui produit l'énergie la plus faible serait celle adoptée par la nature. Cette opération est un peu plus complexe que celle présentée ci-dessus. Un tel calcul est effectué pour la molécule la plus simple, $\\text{H}_2$, [ici.](/learning/courses/quantum-chem-with-vqe/geometry)\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "33231f54-a9c1-499c-a4ad-b4404b843909",
      "metadata": {},
      "source": [
        "<span id=\"4-vqes-relationship-to-other-methods\" />\n",
        "\n",
        "## 4. Relation entre la VQE et d'autres méthodes\n",
        "\n",
        "Dans cette section, nous passerons en revue les avantages et les inconvénients de l'approche originale de l'EQV et soulignerons ses liens avec d'autres algorithmes plus récents.\n",
        "\n",
        "<span id=\"41-the-strengths-and-weaknesses-of-vqe\" />\n",
        "\n",
        "### 4.1 Les forces et les faiblesses du VQE\n",
        "\n",
        "Certains points forts ont déjà été soulignés. Ils comprennent :\n",
        "\n",
        "* Adaptation au matériel moderne : Certains algorithmes quantiques requièrent des taux d'erreur beaucoup plus faibles, ce qui les rapproche d'une tolérance aux pannes à grande échelle. Ce n'est pas le cas de VQE, qui peut être mis en œuvre sur les ordinateurs quantiques actuels.\n",
        "* Circuits peu profonds : La VQE utilise souvent des circuits quantiques relativement peu profonds. La VQE est donc moins sensible aux erreurs de grille accumulées et se prête à de nombreuses techniques d'atténuation des erreurs. Bien entendu, les circuits ne sont pas toujours peu profonds; cela dépend de l'ansatz utilisé.\n",
        "* Polyvalence : L'EQV peut (en principe) être appliquée à tout problème qui peut être considéré comme un problème de valeurs propres ou de vecteurs propres. Il existe de nombreuses mises en garde qui font que l'EQV n'est pas pratique ou désavantageuse pour certains problèmes. Certaines d'entre elles sont récapitulées ci-dessous.\n",
        "\n",
        "Certaines faiblesses de l'EQV et les problèmes pour lesquels elle n'est pas pratique ont également été décrits ci-dessus. Exemples :\n",
        "\n",
        "* Nature heuristique : La VQE ne garantit pas la convergence vers l'énergie correcte de l'état fondamental, car ses performances dépendent du choix de l'ansatz et des méthodes d'optimisation [\\[1-2\\].](#references) Si l'on choisit un ansatz médiocre qui n'offre pas l'intrication nécessaire à l'état fondamental souhaité, aucun optimiseur classique ne peut atteindre cet état fondamental.\n",
        "* Nombreux paramètres potentiels : Un ansatz très expressif peut avoir tellement de paramètres que les itérations de minimisation prennent beaucoup de temps.\n",
        "* Coût de calcul élevé : dans le cadre de la VQE, on utilise un estimateur pour estimer la valeur attendue de chaque terme de l'hamiltonien. La plupart des hamiltoniens d'intérêt comportent des termes qui ne peuvent pas être estimés simultanément. Cela peut rendre la méthode VQE très gourmande en ressources pour les grands systèmes dotés d'hamiltoniens complexes [\\[1\\]](#references).\n",
        "* Effets du bruit : Lorsque l'optimiseur classique recherche un minimum, des calculs bruyants peuvent l'embrouiller et l'éloigner du véritable minimum ou retarder sa convergence. Une solution possible consiste à tirer parti des techniques de pointe en matière d'atténuation et de suppression des erreurs [\\[2-3\\]](#references) sur le site IBM.\n",
        "* Plateaux stériles : Ces régions où les gradients s'évanouissent [\\[2-3\\]](#references) existent même en l'absence de bruit, mais le bruit les rend plus problématiques, car la variation des valeurs attendues due au bruit peut être plus importante que la variation due à la mise à jour des paramètres dans ces régions stériles.\n",
        "\n",
        "<span id=\"42-relationship-to-other-approaches\" />\n",
        "\n",
        "### 4.2 Relation avec d'autres approches\n",
        "\n",
        "<span id=\"adapt-vqe\" />\n",
        "\n",
        "#### Adapt-VQE\n",
        "\n",
        "L'algorithme **ADAPT-VQE** (Adaptive Derivative-Assembled Pseudo-Trotter Variational Quantum Eigensolver) est une amélioration de l'algorithme VQE original, conçu pour améliorer l'efficacité, la précision et l'évolutivité des simulations quantiques, en particulier dans le domaine de la chimie quantique.\n",
        "\n",
        "L'algorithme VQE original décrit tout au long de cette leçon utilise un ansatz fixe prédéfini pour approximer l'état fondamental du système. Dans notre cas, nous avons utilisé `efficient_su2`, avec une seule répétition, en utilisant les portes de rotation Y et RZ.  Bien que les paramètres des portes RZ aient changé, la structure de cet ansatz et les portes utilisées n'ont pas changé.\n",
        "\n",
        "ADAPT-VQE répond aux limitations de VQE par la construction d'un ansatz adaptatif. Au lieu de commencer avec un ansatz fixe, ADAPT-VQE construit dynamiquement l'ansatz de manière itérative. À chaque étape, il sélectionne l'opérateur d'un ensemble prédéfini (comme les opérateurs d'excitation fermionique) qui présente le plus grand gradient par rapport à l'énergie. Cela garantit que seuls les opérateurs les plus importants sont ajoutés, ce qui permet d'obtenir un ansatz compact et efficace [\\[4-6\\].](#references) Cette approche peut avoir plusieurs effets bénéfiques :\n",
        "\n",
        "1. **Réduction de la profondeur du circuit** : En développant l'ansatz de manière incrémentielle et en se concentrant uniquement sur les opérateurs nécessaires, ADAPT-VQE minimise les opérations de porte par rapport aux approches VQE traditionnelles [\\[5,7\\].](#references)\n",
        "2. **Précision améliorée** : La nature adaptative permet à ADAPT-VQE de récupérer davantage d'énergie de corrélation à chaque étape, ce qui la rend particulièrement efficace pour les systèmes fortement corrélés où la VQE traditionnelle a du mal à s'imposer [\\[8,9\\].](#references)\n",
        "3. **Évolutivité et résistance au bruit** : L'ansatz compact réduit l'accumulation d'erreurs de porte, réduit la charge de calcul et limite le nombre de paramètres variationnels qui doivent être minimisés.\n",
        "\n",
        "ADAPT-VQE n'est pas encore parfait. Dans certains cas, il peut être piégé ou ralenti par des minima locaux, et il peut souffrir d'une paramétrisation excessive. Elle peut également être assez gourmande en ressources, car elle nécessite le calcul de gradients et l'optimisation de paramètres avec de nombreuses structures de portes.\n",
        "\n",
        "<span id=\"quantum-phase-estimation-qpe\" />\n",
        "\n",
        "#### Estimation de phase quantique (QPE)\n",
        "\n",
        "L'objectif du QPE est similaire à celui du VQE, mais sa mise en œuvre est très différente. L'EPQ nécessite des ordinateurs quantiques tolérants aux pannes en raison des circuits quantiques généralement profonds et du niveau élevé de cohérence qu'il requiert. Une fois que le QPE pourra être mis en œuvre, il sera plus précis que le VQE. Une façon de décrire la différence est de considérer la précision comme une fonction de la profondeur du circuit. Le QPE permet d'atteindre la précision $\\epsilon$ avec des profondeurs de circuit s'échelonnant jusqu'à $O(1/\\epsilon)$ [\\[10\\].](#references) VQE nécessite $O(1/\\epsilon^2)$ échantillons pour atteindre la même précision [\\[10,11\\].](#references)\n",
        "\n",
        "<span id=\"krylov-sqd-qsci-and-others-in-this-course\" />\n",
        "\n",
        "#### Krylov, SQD, QSCI et autres dans ce cours\n",
        "\n",
        "Le VQE a permis d'établir des algorithmes quantiques qui dépendent encore d'ordinateurs classiques, non seulement pour faire fonctionner l'ordinateur quantique, mais aussi pour des parties substantielles de l'algorithme. Plusieurs de ces algorithmes font l'objet du reste de ce cours. Nous donnons ici une explication succincte de quelques-uns d'entre eux, simplement pour les comparer et les opposer à VQE. Ils seront expliqués plus en détail dans les leçons suivantes.\n",
        "\n",
        "**Diagonalisation quantique de Krylov (KQD)**\n",
        "\n",
        "Les **méthodes de sous-espace de Krylov** permettent de projeter une matrice sur un sous-espace afin de réduire sa dimension et de la rendre plus facile à gérer, tout en conservant les caractéristiques les plus importantes. L'une des astuces de cette méthode consiste à générer un sous-espace qui conserve ces caractéristiques. Il s'avère que la génération de ce sous-espace est étroitement liée à une méthode bien établie sur les ordinateurs quantiques, appelée **Trotterisation**.\n",
        "\n",
        "Il existe quelques variantes des méthodes de Krylov quantique, mais l'approche est généralement la suivante :\n",
        "\n",
        "* Utiliser l'ordinateur quantique pour générer un sous-espace (le sous-espace de Krylov) par trotterisation\n",
        "* Projeter la matrice d'intérêt sur ce sous-espace de Krylov\n",
        "* Diagonaliser le nouvel hamiltonien projeté à l'aide d'un ordinateur classique\n",
        "\n",
        "**Diagonalisation quantique basée sur l'échantillonnage (SQD)**\n",
        "\n",
        "La **diagonalisation quantique basée sur l'échantillonnage (SQD)** est liée à la méthode de Krylov en ce sens qu'elle tente également de réduire la dimension d'une matrice à diagonaliser tout en préservant des caractéristiques essentielles. La SQD procède de la manière suivante :\n",
        "\n",
        "* Commencez par une estimation initiale de votre état fondamental et préparez le système dans cet état fondamental.\n",
        "* Utilisez Sampler pour échantillonner les chaînes de bits qui composent cet état.\n",
        "* Utilisez la collection d'états de base de calcul de l'échantillonneur comme sous-espace sur lequel vous projetez votre matrice d'intérêt.\n",
        "* Diagonaliser la plus petite matrice projetée à l'aide d'un ordinateur classique.\n",
        "\n",
        "Elle est liée à la VQE en ce sens qu'elle exploite l'informatique classique et quantique pour des composants algorithmiques importants. Elles ont toutes deux en commun l'obligation de préparer une bonne estimation initiale ou un bon ansatz. Mais la répartition du travail entre l'ordinateur classique et l'ordinateur quantique dans la SQD ressemble davantage à celle de la méthode de Krylov.\n",
        "\n",
        "En fait, la méthode de Krylov et la SQD ont récemment été combinées dans la méthode de diagonalisation quantique de Krylov basée sur l'échantillonnage (SKQD) [\\[12\\].](#references)\n",
        "\n",
        "**Interaction de la configuration du sous-espace quantique**\n",
        "\n",
        "L' **interaction de configuration sélectionnée quantique (QSCI**[ )\\[13\\]](#references) est un algorithme qui produit un état fondamental approximatif d'un hamiltonien en échantillonnant une fonction d'onde d'essai afin d'identifier les états de base de calcul significatifs pour générer un sous-espace pour une diagonalisation classique.\n",
        "La SQD et la QSCI utilisent toutes deux un ordinateur quantique pour construire un sous-espace réduit.  La force supplémentaire de QSCI réside dans la préparation des États, en particulier dans le contexte des problèmes de chimie. Il tire parti de diverses stratégies telles que l'utilisation d'états évoluant dans le temps [\\[14\\]](#references) et d'un ensemble de réponses inspirées de la chimie. En se concentrant sur la préparation efficace des états, QSCI réduit les coûts de calcul quantique pour les hamiltoniens chimiques tout en maintenant une grande fidélité et en tirant parti de la robustesse au bruit des techniques d'échantillonnage d'états quantiques [\\[15\\].](#references) QSCI propose également une technique de construction adaptative qui fournit plus de réponses pour un meilleur résultat.\n",
        "\n",
        "Le flux de travail par défaut de QSCI pour les problèmes de chimie est le suivant :\n",
        "\n",
        "* Construisez l'hamiltonien moléculaire à l'aide du logiciel de votre choix (tel que SciPy ).\n",
        "* Préparez un algorithme QSCI en sélectionnant un état initial approprié et un ansatz inspiré de la chimie avec un ensemble de paramètres présélectionnés.\n",
        "* Échantillonnez des états de base significatifs et diagonalisez l'hamiltonien à l'aide d'un ordinateur classique pour obtenir l'énergie de l'état fondamental.\n",
        "* On a souvent recours à la récupération de configuration [\\[16\\]](#references) et à la post-sélection de symétrie [\\[15\\]](#references) comme techniques de post-traitement.\n",
        "* En option, le flux de travail de la QSCI adaptative comporte une boucle d'optimisation supplémentaire de step2 à step3, en utilisant davantage de réponses avec des états initiaux aléatoires.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Vérifiez votre compréhension\n",
        "\n",
        "Qu'est-ce que la VQE a en commun avec toutes les autres méthodes énumérées ci-dessus (à l'exception de la QPE, qui n'est pas décrite en détail)?\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Réponse\">\n",
        "    Tous impliquent un état d'essai ou une fonction d'onde d'une sorte ou d'une autre. Tout fonctionne mieux lorsque l'estimation initiale de cet état d'essai est excellente.\n",
        "\n",
        "    Une autre réponse correcte est qu'elles sont toutes plus faciles à mettre en œuvre lorsque l'hamiltonien est facile à mesurer (peut être trié en un nombre relativement restreint de groupes d'opérateurs de Pauli commutés).\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Qu'est-ce que la VQE a en commun avec aucune des autres méthodes énumérées ci-dessus?\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Réponse\">\n",
        "    Optimiseurs classiques. Aucun des autres n'utilise d'algorithmes d'optimisation classiques pour sélectionner les paramètres variationnels.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8086b6a5-daf2-457b-bc7a-84db943b333f",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## Références\n",
        "\n",
        "\\[2] [https://en.wikipedia.org/wiki/Variational\\_quantum\\_eigensolver](https://en.wikipedia.org/wiki/Variational_quantum_eigensolver)\n",
        "\n",
        "\\[3] [https://journals.aps.org/prapplied/abstract/10.1103/PhysRevApplied.19.024047](https://journals.aps.org/prapplied/abstract/10.1103/PhysRevApplied.19.024047)\n",
        "\n",
        "\\[4] [https://arxiv.org/abs/2111.05176](https://arxiv.org/abs/2111.05176)\n",
        "\n",
        "\\[6] [https://inquanto.quantinuum.com/tutorials/InQ\\_tut\\_fe4n2\\_2.html](https://inquanto.quantinuum.com/tutorials/InQ_tut_fe4n2_2.html)\n",
        "\n",
        "\\[7] [https://www.nature.com/articles/s41467-019-10988-2](https://www.nature.com/articles/s41467-019-10988-2)\n",
        "\n",
        "\\[8] [https://arxiv.org/abs/2210.15438](https://arxiv.org/abs/2210.15438)\n",
        "\n",
        "\\[9] [https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.6.013254](https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.6.013254)\n",
        "\n",
        "\\[10] [https://arxiv.org/html/2403.09624v1](https://arxiv.org/html/2403.09624v1)\n",
        "\n",
        "\\[11] [https://www.nature.com/articles/s42005-023-01312-y](https://www.nature.com/articles/s42005-023-01312-y)\n",
        "\n",
        "\\[13] [https://arxiv.org/abs/1802.00171](https://arxiv.org/abs/1802.00171)\n",
        "\n",
        "\\[14] [https://arxiv.org/abs/2103.08505](https://arxiv.org/abs/2103.08505)\n",
        "\n",
        "\\[15] [https://arxiv.org/html/2501.09702v1](https://arxiv.org/html/2501.09702v1)\n",
        "\n",
        "\\[16] [https://quri-sdk.qunasys.com/docs/examples/quri-algo-vm/qsci/](https://quri-sdk.qunasys.com/docs/examples/quri-algo-vm/qsci/)\n",
        "\n",
        "\\[17] [https://arxiv.org/abs/2412.13839](https://arxiv.org/abs/2412.13839)\n",
        "\n",
        "\\[18] [https://arxiv.org/abs/2302.11320v1](https://arxiv.org/abs/2302.11320v1)\n",
        "\n",
        "\\[19] [https://arxiv.org/pdf/2405.05068v1](https://arxiv.org/pdf/2405.05068v1)\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": 2
}