{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "14a84dc4",
   "metadata": {},
   "source": [
    "# Programmation quantique\n",
    "## Notebook #2. Problème de Bernstein-Vazirani\n",
    "\n",
    "Ce notebook est à compléter avec vos réponses puis à déposer sur la page Celene du cours __programmation quantique__ dans le dépôt aproprié avant le 19 novembre."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb088050",
   "metadata": {},
   "source": [
    "**À vous de jouer !** Nous avons étudié en détail le problème de Bernstein-Vazirani, en cours et en TD. Dans ce notebook vous allez reproduire ce problème, simuler la solution et illustrer la démonstration. Nous vous fournissons la trame, nous attendons de vous bien plus que du code : il s'agit d'expliquer, de commenter et de coder."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "064383e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit import QuantumCircuit, transpile\n",
    "from qiskit.providers.basic_provider import BasicProvider\n",
    "from qiskit.visualization import plot_histogram\n",
    "from qiskit.quantum_info import Operator\n",
    "\n",
    "# Un simulateur de circuit complet\n",
    "sim = BasicProvider().get_backend('basic_simulator')\n",
    "\n",
    "# Afficher un circuit\n",
    "def draw_circ(circ): display(circ.draw(output='mpl'))\n",
    "    \n",
    "def show(circ):\n",
    "    draw_circ(circ)\n",
    "    display(Operator(circ).draw('latex'))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa08816b",
   "metadata": {},
   "source": [
    "## 1. Produit scalaire\n",
    "\n",
    "Dans le problème de Bernstein-Vazirani, l'entrée du problème est un circuit quantique, considéré comme une boîte noire, dont on sait qu'il calcule un produit scalaire :\n",
    "$$\n",
    "f(\\left|x_1 x_2 \\cdots x_n\\right>) = x_1 s_1 \\oplus x_2 s_2 \\oplus \\cdots \\oplus x_n s_n\n",
    "$$\n",
    "\n",
    "La manière dont le circuit calcule cette fonction n'a pas d'importance. Il peut utiliser des qubits auxiliaire initialisés à 0 du moment qu'il les retourne à 0 après utilisation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a58eb407",
   "metadata": {},
   "outputs": [],
   "source": [
    "### TODO écrire 2 mises en œuvre du calcul du produit scalaire :\n",
    "###   1. la version directe qui calcule en enchaînant les CNOT sur les x_i pour s_i=1\n",
    "###   2. une version plus alambiquée qui utilise des bits auxiliaires et mélange un peu le calcul\n",
    "### Vos fonctions doivent prendre en paramètre le vecteur s (sous forme de tableau) \n",
    "### et retourner un QuantumCircuit dont les n premiers bits attendent l'entrée, le n+1 eme produit\n",
    "### la sortie et les bits restant sont les auxiliaires."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ffdc1763",
   "metadata": {},
   "source": [
    "Pensez à vérifier par quelques tests que vos fonctions font bien ce qui est attendu. Vous pouvez par exemple tirer quelques vecteurs au hasard et comparer ce que donne la simulation quiskit par rapport à un calcul direct du produit scalaire.\n",
    "\n",
    "Prenez le temps de faire quelque chose de joli !"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8eedb3c5",
   "metadata": {},
   "outputs": [],
   "source": [
    "### TODO faire des tests convaincants :)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d821e90d",
   "metadata": {},
   "source": [
    "## 2. Algorithme de Bernstein-Vazirani\n",
    "\n",
    "Expliquez comment l'algorithme fonctionne en quelques phrases puis codez-le !"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "bcb4daba",
   "metadata": {},
   "outputs": [],
   "source": [
    "### TODO écrire une fonction qui prend en paramètre la taille n du vecteur, \n",
    "### un circuit boîte noire dont les n premiers bits attendent l'entrée et \n",
    "### le n+1 eme retourne la sortie (les autres bits sont les auxiliaires)\n",
    "### Cette fonction doit retourner le circuit complet pour Bernstein-Vazirani\n",
    "### Avec des barrières avant et après le circuit boîte noire."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13e2beff",
   "metadata": {},
   "source": [
    "Montrez par simulation, avec un unique run, que le circuit construit est capable de retrouver le vecteur."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "4d8e3932",
   "metadata": {},
   "outputs": [],
   "source": [
    "### TODO démonstration par simulation ! Testez votre fonction sur vos deux mises en œuvre !"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7708214b",
   "metadata": {},
   "source": [
    "## 3. Démonstration\n",
    "\n",
    "La démonstration combinatoire repose sur deux égalités entre circuits. Présentez ces deux égalités en construisant les circuits et en montrant avec `Operator` qu'ils sont bien égaux."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "72872895",
   "metadata": {},
   "outputs": [],
   "source": [
    "### TODO les deux égalités entre circuits qui sont au cœur de la démonstration"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9af745b6",
   "metadata": {},
   "source": [
    "Expliquez la démonstration en illustrant la transformation progressive de la version directe du circuit de produit scalaire. Idéalement on voudrait visualier cette transformation étape par étape sur un exemple de 4 à 5 qubits d'entrée."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "82721b76",
   "metadata": {},
   "outputs": [],
   "source": [
    "### TODO démonstration combinatoire par transformation de circuit"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "663a2a1e",
   "metadata": {},
   "source": [
    "## 4. Exécution à distance (BONUS)\n",
    "\n",
    "Utilisez `qiskit_ibm_runtime` pour effectuer une exécution de l'algorithme à distance sur un vrai processeur quantique."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "9f43fc90",
   "metadata": {},
   "outputs": [],
   "source": [
    "### TODO exécution sur le runtime IBM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ca0d66ba",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "qiskitenv",
   "language": "python",
   "name": "qiskitenv"
  },
  "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.9.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
