{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "dd33e9e7-3e4c-48ea-81a9-70b74c34b130",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Transformação de Fourier quântica\"\n",
        "description: \"Aprenda sobre a transformada de Fourier quântica e como ela é usada como sub-rotina em algoritmos como a estimativa de fase quântica.\"\n",
        "---\n",
        "\n",
        "<span id=\"quantum-fourier-transform\" />\n",
        "\n",
        "# Transformação de Fourier quântica\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a920f884-f6b0-46fd-a4ef-126f9c281f17",
      "metadata": {},
      "source": [
        "Para este módulo do Qiskit in Classrooms, os alunos devem ter um ambiente de trabalho Python com os seguintes pacotes instalados:\n",
        "\n",
        "* `qiskit` v2.1.0 ou mais recente\n",
        "* `qiskit-ibm-runtime` v0.40.1 ou mais recente\n",
        "* `qiskit-aer` v0.17.0 ou mais recente\n",
        "* `qiskit.visualization`\n",
        "* `numpy`\n",
        "* `pylatexenc`\n",
        "\n",
        "Para configurar e instalar os pacotes acima, consulte o guia [Instalar o Qiskit](/docs/guides/install-qiskit).\n",
        "Para executar trabalhos em computadores quânticos reais, os alunos precisarão configurar uma conta no site IBM Quantum® seguindo as etapas do guia [Configurar sua conta IBM Cloud](/docs/guides/cloud-setup).\n",
        "\n",
        "Esse módulo foi testado e usou 13 segundos de tempo de QPU. Essa é uma estimativa de boa-fé; seu uso real pode variar.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "46231c35-a3f5-4b04-83c5-6f15d6a5785c",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Uncomment and modify this line as needed to install dependencies\n",
        "#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d77edd39-2574-41bb-9338-13d139f1a6a9",
      "metadata": {},
      "source": [
        "<span id=\"introduction\" />\n",
        "\n",
        "## Introdução\n",
        "\n",
        "A transformada de Fourier é uma ferramenta onipresente com aplicações em matemática, física, processamento de sinais, compactação de dados e inúmeros outros campos. Uma versão *quântica* da transformada de Fourier, apropriadamente chamada de transformada quântica de Fourier, forma a base de alguns dos algoritmos quânticos mais importantes.\n",
        "\n",
        "Hoje, depois de relembrarmos a transformada de Fourier clássica, falaremos sobre como implementamos a transformada de Fourier quântica em um computador quântico. Em seguida, discutiremos uma das aplicações da transformada quântica de Fourier em um algoritmo chamado algoritmo de estimativa de fase. A estimativa de fase quântica é uma sub-rotina do famoso algoritmo de fatoração de Shor, que às vezes é chamado de \"joia da coroa\" da computação quântica. Este módulo se baseia em outro módulo sobre o algoritmo do Shor, mas também foi criado para ser autônomo. A transformada quântica de Fourier é um algoritmo fascinante e útil por si só!\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "24e8de09-0876-46cd-9346-c0d46ffce8a9",
      "metadata": {},
      "source": [
        "<span id=\"the-classical-fourier-transform\" />\n",
        "\n",
        "## A transformada clássica de Fourier\n",
        "\n",
        "Antes de entrarmos na transformada quântica de Fourier, vamos primeiro nos lembrar da versão clássica. A transformada de Fourier é um método de transformação de uma \"base\" para outra. Você pode pensar em duas bases como perspectivas diferentes do mesmo problema - ambas são formas válidas de expressar uma função, mas uma ou outra pode ser mais esclarecedora, dependendo do problema em questão. Alguns exemplos de pares de bases que são conectados pela transformada de Fourier são posição e momento, e tempo e frequência.\n",
        "\n",
        "Vejamos um exemplo de como a transformada de Fourier pode nos ajudar a descobrir que nota um instrumento está tocando com base em sua forma de onda de áudio. Normalmente, vemos as formas de onda representadas na base de tempo, ou seja, a amplitude da onda é expressa como uma função do tempo.\n",
        "\n",
        "![Sinal senoidal único plotado como uma função do tempo.](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/Cnote.avif)\n",
        "\n",
        "Podemos transformar essa forma de onda em Fourier para passar da base de tempo para a base de frequência:\n",
        "\n",
        "![Espectro de frequência da forma de onda de áudio. Um pico nítido e claro em 260 Hz.](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/Cnotefreq.avif)\n",
        "\n",
        "Na base de frequência, podemos ver facilmente um pico claro em cerca de 260 Hz. Isso é um dó médio!\n",
        "\n",
        "Agora, você pode ter conseguido determinar que um dó médio estava sendo tocado sem o uso de uma transformada de Fourier, mas e se várias notas forem tocadas ao mesmo tempo? Em seguida, a forma de onda se torna mais complicada quando a plotamos na base de tempo:\n",
        "\n",
        "![Gráfico de deslocamento versus tempo de várias ondas senoidais ao mesmo tempo, criando um padrão periódico mais complicado.](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/Cchord.avif)\n",
        "\n",
        "Mas o espectro de frequência identifica claramente três picos:\n",
        "\n",
        "![Espectro de frequência da forma de onda de áudio acima. Três picos em aproximadamente 260 Hz, 330 Hz e 392 Hz. O último pico é muito fraco, mas visível.](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/Cchordfreq.avif)\n",
        "\n",
        "Esse foi um acorde de dó maior, tocando as notas dó, mi e sol.\n",
        "\n",
        "Esse tipo de análise de Fourier pode nos ajudar a extrair os componentes de frequência de qualquer tipo de sinal complicado.\n",
        "\n",
        "<span id=\"discrete-fourier-transform\" />\n",
        "\n",
        "### Transformada discreta de Fourier\n",
        "\n",
        "A transformada de Fourier é útil para várias aplicações de processamento de sinais. Mas na maioria desses aplicativos do mundo real (incluindo o exemplo de música que usamos acima), queremos transformar um conjunto discreto de $N$ pontos de dados - não uma função contínua. Nesse caso, usamos a transformada *discreta* de Fourier. A transformada discreta de Fourier (DFT) atua em um vetor $(x_0, ..., x_{N-1})$ e o mapeia para o vetor $(y_0, ..., y_{N-1})$ de acordo com a fórmula:\n",
        "\n",
        "$y_k = \\frac{1}{\\sqrt{N}}\\sum_{j=0}^{N-1}x_j\\omega_N^{jk}$\n",
        "\n",
        "onde tomamos $\\omega_N^{jk} = e^{2\\pi i \\frac{jk}{N}}$. (Observe que há outras convenções que têm um sinal de menos no exponencial, portanto, tenha cuidado ao ver a DFT na natureza) Lembre-se de que $e^{2\\pi i \\frac{jk}{N}}$ é uma função periódica, com período $\\frac{N}{k}$. Portanto, ao multiplicar por essa função, a transformada de Fourier é essencialmente uma forma de decompor a função (discreta) $\\{x_{j}\\}$ em uma combinação linear de suas funções periódicas constituintes, cada uma com período $\\frac{N}{k}$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e1271322-48e3-47e1-90e1-7cf7117ccd7c",
      "metadata": {},
      "source": [
        "<span id=\"the-quantum-fourier-transform\" />\n",
        "\n",
        "## A transformada de Fourier quântica\n",
        "\n",
        "Agora, vimos como a transformada de Fourier é usada para representar uma função como uma combinação linear de um novo conjunto das chamadas \"funções de base\" As transformações de base também são feitas regularmente em estados de qubit. Por exemplo, o estado de um único qubit $|\\psi\\rangle$ pode ser expresso na base computacional $|\\psi\\rangle = c_0 |0\\rangle + c_1 |1\\rangle$, com os estados da base $|0\\rangle$ e $|1\\rangle$, ou na base $X$ $|\\psi\\rangle = c_+ |+\\rangle + c_- |-\\rangle$ com os estados da base $|+\\rangle = \\frac{1}{\\sqrt{2}} (|0\\rangle + |1\\rangle)$ e $|-\\rangle = \\frac{1}{\\sqrt{2}} (|0\\rangle - |1\\rangle)$. Ambas são igualmente válidas, mas uma pode ser mais natural do que a outra, dependendo do tipo de problema que você está tentando resolver.\n",
        "\n",
        "Os estados de Qubit também podem ser expressos na base de Fourier, em que um estado é expresso em termos de uma combinação linear dos estados da base de Fourier $|\\phi_y\\rangle$, em vez dos estados usuais da base computacional, $|x\\rangle$. Para fazer isso, você precisa aplicar uma transformada quântica de Fourier (QFT):\n",
        "\n",
        "$ | \\phi_y \\rangle =  \\frac{1}{\\sqrt{N}}\\sum_{x=0}^{N-1}\\omega_N^{y x} \\vert x \\rangle$\n",
        "\n",
        "com $\\omega_N^{yx} = e^{\\frac{2\\pi i y x}{N}}$ como acima, e $N$ é o número de estados básicos no seu sistema quântico. Observe que, como estamos trabalhando com qubits agora, $m$ qubits fornece $2^m$ estados básicos, portanto $N=2^m$. Aqui, os estados básicos são escritos como um único número $|x\\rangle$, onde $x$ varia de $0$ a $N-1$, mas é mais comum ver os estados básicos expressos como $|00...00\\rangle$, $|00...01\\rangle$, $|00...11\\rangle$,..., $|11...11\\rangle$, onde cada dígito binário representa o estado do qubit 0 a $m-1$, da direita para a esquerda. Existe uma maneira fácil de converter esses estados binários em um único número: basta tratá-los como números binários! Portanto, $|00...00\\rangle = |0\\rangle$, $|00...01\\rangle = |1\\rangle$, $|00...10\\rangle = |2\\rangle$, $|00...11\\rangle = |3\\rangle$ e assim por diante, até $|11...11\\rangle = |2^m -1\\rangle = |N-1\\rangle$.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "07d09c65-9ba8-41cb-983d-b5dd33d99458",
      "metadata": {},
      "source": [
        "<span id=\"build-intuition-for-the-fourier-basis-states\" />\n",
        "\n",
        "### Desenvolva a intuição para os estados básicos de Fourier\n",
        "\n",
        "Portanto, acabamos de explicar o que são os estados da base computacional e como eles são ordenados: são o conjunto de estados em que cada qubit está em $0$ ou $1$, e os ordenamos a partir do estado em que todos os qubits são $0$, $|00...00\\rangle$, até o estado em que todos são $1$, $|11...11\\rangle$.\n",
        "\n",
        "Mas como podemos entender os estados da base de *Fourier*? Todos os estados da base de Fourier são superposições iguais de todos os estados da base computacional, mas cada estado difere do outro na periodicidade da *fase* dos componentes. Para entender isso de forma mais concreta, vamos dar uma olhada nos quatro estados da base de Fourier de um sistema de dois qubits. O estado de Fourier mais baixo é aquele cuja fase não varia de forma alguma:\n",
        "\n",
        "$|\\phi_0\\rangle = \\frac{1}{2} (|00\\rangle + |01\\rangle + |10\\rangle + |11\\rangle)$\n",
        "\n",
        "Podemos visualizar esse estado traçando a amplitude complexa de cada um dos termos. A linha vermelha guia o olho para mostrar como a fase dessa amplitude gira em torno do plano complexo como uma função do estado da base computacional. Para $|\\phi_0\\rangle$, a fase permanece constante:\n",
        "\n",
        "![Gráfico de barras da amplitude complexa (plano x-y) para cada estado da base computacional (eixo z) para phi\\_0. Todos eles são reais e, portanto, as barras apontam para +1 no eixo x](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/phi0.avif)\n",
        "\n",
        "O próximo estado da base de Fourier é aquele cujas fases dos componentes variam de $0$ a $2\\pi$ apenas uma vez:\n",
        "\n",
        "$|\\phi_1\\rangle = \\frac{1}{2} (|00\\rangle + e^{i\\pi/2}|01\\rangle + e^{i\\pi}|10\\rangle + e^{3i\\pi/2}|11\\rangle) = \\frac{1}{2}(|00\\rangle + i|01\\rangle - |10\\rangle - i|11\\rangle)$\n",
        "\n",
        "E podemos ver esse enrolamento no gráfico da amplitude complexa em relação ao estado da base computacional:\n",
        "\n",
        "![Gráfico de barras da amplitude complexa (plano x-y) para cada estado da base computacional (eixo z) para phi\\_1. A linha vermelha mostra como a fase complexa se acumula de tal forma que ela gira em torno de 2\\pi uma vez à medida que você passa por todos os estados da base computacional.](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/phi1.avif)\n",
        "\n",
        "Portanto, cada estado tem uma fase que é $2\\pi/4$ radianos mais alta do que o estado anterior quando ordenado da maneira padrão, já que neste exemplo temos quatro estados básicos ( $N=4$ ). O próximo estado da base vai de 0 a 2 $\\pi$ duas vezes:\n",
        "\n",
        "$|\\phi_2\\rangle = \\frac{1}{2} (|00\\rangle + e^{i\\pi}|01\\rangle + e^{2i\\pi}|10\\rangle + e^{3i\\pi}|11\\rangle) = \\frac{1}{2} (|00\\rangle - |01\\rangle + |10\\rangle - |11\\rangle)$\n",
        "\n",
        "![Gráfico de barras da amplitude complexa (plano x-y) para cada estado da base computacional (eixo z) para phi\\_2. A linha vermelha mostra como a fase complexa se acumula de tal forma que gira em torno de 2\\pi duas vezes à medida que você passa por todos os estados da base computacional.](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/phi2.avif)\n",
        "\n",
        "Por fim, o componente de Fourier mais alto é aquele com a fase de variação mais rápida. Em nosso exemplo com dois qubits, é aquele cujas fases variam de 0 a $2\\pi$ três vezes:\n",
        "\n",
        "$|\\phi_3\\rangle = \\frac{1}{2} (|00\\rangle + e^{3i\\pi/2}|01\\rangle + e^{6i\\pi/2}|10\\rangle + e^{9i\\pi/2}|11\\rangle) = \\frac{1}{2} (|00\\rangle - i|01\\rangle - |10\\rangle + i|11\\rangle)$\n",
        "\n",
        "![Gráfico de barras da amplitude complexa (plano x-y) para cada estado da base computacional (eixo z) para phi\\_3. A linha vermelha mostra como a fase complexa se acumula de tal forma que ela gira em torno de 2\\pi três vezes à medida que você passa por todos os estados da base computacional.](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/phi3.avif)\n",
        "\n",
        "Em geral, para um estado de qubit $m$, haverá um $2^m$ e estados de base de Fourier, cuja variação de fase varia de constante, para $|\\phi_0\\rangle$, a rapidamente variável para $|\\phi_{2^m-1}\\rangle$, completando $2^m-1$ voltas em torno de $2\\pi$ sobre a superposição de estados. Portanto, quando fazemos uma QFT de um estado quântico, estamos essencialmente fazendo a mesma análise básica que fizemos para a forma de onda musical na introdução. Estamos determinando os componentes de frequência de Fourier que contribuem para criar o estado quântico de interesse.\n",
        "\n",
        "<span id=\"try-some-example-qfts\" />\n",
        "\n",
        "### Experimente alguns exemplos de QFTs\n",
        "\n",
        "Vamos tentar continuar a construir nossa intuição para a transformada quântica de Fourier criando um estado na base computacional e, em seguida, vendo o que acontece quando aplicamos a QFT a ele. Por enquanto, trataremos o QFT apenas como uma caixa preta que aplicamos usando o site `QFTGate` da [biblioteca de circuitos Qiskit.](/docs/guides/circuit-library) Mais tarde, daremos uma olhada nos bastidores para ver como isso é implementado.\n",
        "\n",
        "Começamos carregando os pacotes necessários e selecionando um dispositivo para executar nosso circuito:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "3b420ee9-fe1f-4f29-aa73-1306e7a86688",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.visualization import plot_histogram\n",
        "from qiskit.circuit.library import QFTGate"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "f93e8786-96e4-4adf-97b1-1d6c1222b3dc",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "ibm_pinguino2\n"
          ]
        }
      ],
      "source": [
        "# Load the Qiskit Runtime service\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "# Load the Runtime primitive and session\n",
        "from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "\n",
        "# Use the least busy backend\n",
        "# backend = service.least_busy(operational=True, simulator=False, min_num_qubits = 127)\n",
        "backend = service.backend(\"ibm_pinguino2\")\n",
        "\n",
        "print(backend.name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ea5beb2c-d7b2-4d7b-9015-02dad90d44b6",
      "metadata": {},
      "source": [
        "Se você não tiver tempo disponível em sua conta ou quiser usar um simulador por qualquer motivo, poderá executar a célula abaixo para configurar um simulador que imitará o dispositivo quântico que selecionamos acima:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "7f33f044-a798-4b9c-baad-6676650cd322",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Load the backend sampler\n",
        "from qiskit.primitives import BackendSamplerV2\n",
        "\n",
        "# Load the Aer simulator and generate a noise model based on the currently-selected backend.\n",
        "from qiskit_aer import AerSimulator\n",
        "from qiskit_aer.noise import NoiseModel\n",
        "\n",
        "noise_model = NoiseModel.from_backend(backend)\n",
        "\n",
        "# Define a simulator using Aer, and use it in Sampler.\n",
        "backend_sim = AerSimulator(noise_model=noise_model)\n",
        "sampler_sim = BackendSamplerV2(backend=backend_sim)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "1d4d986a-6164-40cd-8bba-0289af2430f4",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Alternatively, load a fake backend with generic properties and define a simulator.\n",
        "from qiskit.providers.fake_provider import GenericBackendV2\n",
        "\n",
        "backend_gen = GenericBackendV2(num_qubits=18)\n",
        "sampler_gen = BackendSamplerV2(backend=backend_gen)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bce6f65e-1105-4abf-80ab-476385ff5b60",
      "metadata": {},
      "source": [
        "<span id=\"single-computational-basis-state\" />\n",
        "\n",
        "#### Estado de base computacional único\n",
        "\n",
        "Primeiro, vamos tentar transformar um único estado de base computacional. Começaremos criando um estado computacional aleatório:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "79943d18-2d57-41f4-ba6e-9c40aca24d38",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/79943d18-2d57-41f4-ba6e-9c40aca24d38-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 1: Map\n",
        "\n",
        "qubits = 4\n",
        "N = 2**qubits\n",
        "\n",
        "\n",
        "qc = QuantumCircuit(qubits)\n",
        "\n",
        "# flip state of random qubits to put in a random single computational basis state\n",
        "for i in range(1, qubits):\n",
        "    if np.random.randint(0, 2):\n",
        "        qc.x(i)\n",
        "\n",
        "\n",
        "# make a copy of the above circuit. (to be used when we apply the QFT in next part)\n",
        "qc_qft = qc.copy()\n",
        "\n",
        "\n",
        "qc.measure_all()\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "c16bbbb1-99fe-4824-b9a5-b74fa79eeedf",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/c16bbbb1-99fe-4824-b9a5-b74fa79eeedf-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 2: Transpile\n",
        "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",
        "qc_isa = pm.run(qc)\n",
        "\n",
        "# Step 3: Run the job on a real quantum computer OR try fake backend\n",
        "\n",
        "sampler = Sampler(mode=backend)\n",
        "pubs = [qc_isa]\n",
        "\n",
        "# Run the job on real quantum device\n",
        "\n",
        "job = sampler.run(pubs, shots=1000)\n",
        "res = job.result()\n",
        "counts = res[0].data.meas.get_counts()\n",
        "\n",
        "# OR Run the job on the Aer simulator with noise model from real backend\n",
        "\n",
        "# job = sampler_sim.run([qc_isa])\n",
        "# res = job.result()\n",
        "# counts = res[0].data.meas.get_counts()\n",
        "\n",
        "# Step 4: Post-Process\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f3723281-56f2-42ac-afd9-44f6d0fe147b",
      "metadata": {},
      "source": [
        "Agora, vamos fazer a transformação de Fourier desse estado com `QFTGate`:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "51b45910-624c-40ee-ad56-d9af094490d2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/51b45910-624c-40ee-ad56-d9af094490d2-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 1: Map\n",
        "\n",
        "qc_qft.compose(QFTGate(qubits), inplace=True)\n",
        "qc_qft.measure_all()\n",
        "qc_qft.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "198a4223-96ab-475e-a83c-75596bf569cb",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/198a4223-96ab-475e-a83c-75596bf569cb-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 2: Transpile\n",
        "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",
        "qc_isa = pm.run(qc_qft)\n",
        "\n",
        "# Step 3: Run the job on a real quantum computer - try fake backend\n",
        "\n",
        "sampler = Sampler(mode=backend)\n",
        "pubs = [qc_isa]\n",
        "\n",
        "# Run the job on real quantum device\n",
        "\n",
        "job = sampler.run(pubs, shots=1000)\n",
        "res = job.result()\n",
        "counts = res[0].data.meas.get_counts()\n",
        "\n",
        "# OR Run the job on the Aer simulator with noise model from real backend\n",
        "\n",
        "# job = sampler_sim.run([qc_isa])\n",
        "# res = job.result()\n",
        "# counts = res[0].data.meas.get_counts()\n",
        "\n",
        "# Step 4: Post-Process\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "89965746-e7d1-409f-a893-5766759a8ce3",
      "metadata": {},
      "source": [
        "Como você pode ver, medimos as populações de cada estado para que sejam mais ou menos iguais, com ou sem algum ruído experimental e estatístico. Portanto, se você pegar a QFT de um único estado da base computacional, o resultado será uma superposição igual de todos os estados. Se você estiver familiarizado com as transformadas de Fourier, isso provavelmente não o surpreenderá. Um princípio básico que pode nos ajudar a criar uma conexão intuitiva entre uma função e sua transformada de Fourier é que a largura de uma função é inversamente proporcional à largura de sua transformada de Fourier. Portanto, algo que é muito localizado no tempo, por exemplo, como um pulso muito curto, exigirá uma ampla gama de frequências para gerar esse pulso. Esse sinal será muito amplo no espaço de Fourier.\n",
        "\n",
        "Na verdade, esse fato está relacionado à incerteza quântica! O princípio da incerteza de Heisenberg é normalmente declarado como $\\Delta x \\Delta p \\ge \\hbar / 2 $. Portanto, se a incerteza em $x$ ( $\\Delta x$ ) for pequena, a incerteza no momento ( $\\Delta p$ ) deve ser grande e vice-versa. Acontece que a transformação da base de posição $x$ para a base de momento $p$ é realizada por meio de uma transformada de Fourier.\n",
        "\n",
        "Observação: lembre-se de que estamos medindo as populações em cada um dos estados da base, portanto, estamos perdendo informações sobre as fases relativas entre as várias partes da superposição. Portanto, embora o QFT de qualquer estado de base computacional único produza a mesma distribuição uniforme na população em todos os estados de base, as *fases* não serão necessariamente as mesmas.\n",
        "\n",
        "<span id=\"two-computational-basis-states\" />\n",
        "\n",
        "#### Dois estados de base computacional\n",
        "\n",
        "Agora, vamos ver o que acontece quando preparamos uma superposição de estados da base computacional. Como você acha que será a transformada de Fourier nesse caso?\n",
        "\n",
        "Vamos escolher a superposição:\n",
        "\n",
        "$|\\psi\\rangle = \\frac{1}{\\sqrt{2}} (|0\\rangle + |N/2\\rangle) = \\frac{1}{\\sqrt{2}} (|000...0\\rangle + |100...0\\rangle)$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "cd0b237b-b139-451a-8170-69babdc29e56",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/cd0b237b-b139-451a-8170-69babdc29e56-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 1: Map\n",
        "qubits = 4\n",
        "N = 2**qubits\n",
        "\n",
        "\n",
        "qc = QuantumCircuit(qubits)\n",
        "\n",
        "# To make this state, we just need to apply a Hadamard to the last qubit\n",
        "\n",
        "qc.h(qubits - 1)\n",
        "\n",
        "\n",
        "qc_qft = qc.copy()\n",
        "\n",
        "\n",
        "qc.measure_all()\n",
        "\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "0ad8006b-caaf-4e4c-b222-a9224d3f6af8",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/0ad8006b-caaf-4e4c-b222-a9224d3f6af8-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# First, let's go through steps 2-4 for the first circuit, qc\n",
        "\n",
        "# Step 2: Transpile\n",
        "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",
        "qc_isa = pm.run(qc)\n",
        "\n",
        "# Step 3: Run the job on a real quantum computer - try fake backend\n",
        "\n",
        "sampler = Sampler(mode=backend)\n",
        "pubs = [qc_isa]\n",
        "\n",
        "# Run the job on real quantum device\n",
        "\n",
        "job = sampler.run(pubs, shots=1000)\n",
        "res = job.result()\n",
        "counts = res[0].data.meas.get_counts()\n",
        "\n",
        "# OR run the job on the Aer simulator with noise model from real backend\n",
        "\n",
        "# job = sampler_sim.run([qc_isa])\n",
        "# res = job.result()\n",
        "# counts = res[0].data.meas.get_counts()\n",
        "\n",
        "# Step 4: Post-process\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "93aaa06c-7de3-4c0f-950c-e48768ca50c5",
      "metadata": {},
      "source": [
        "Agora, vamos fazer a transformação de Fourier desse estado com `QFTGate`:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "11793bc2-53ea-4c34-aed7-06e1ce630557",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/11793bc2-53ea-4c34-aed7-06e1ce630557-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 1: Map\n",
        "\n",
        "qc_qft.compose(QFTGate(qubits), inplace=True)\n",
        "qc_qft.measure_all()\n",
        "qc_qft.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "15b9688a-8c71-457d-87e7-8bfec6f4ee76",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/15b9688a-8c71-457d-87e7-8bfec6f4ee76-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 2: Transpile\n",
        "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",
        "qc_isa = pm.run(qc_qft)\n",
        "\n",
        "# Step 3: Run the job on a real quantum computer OR try fake backend\n",
        "\n",
        "sampler = Sampler(mode=backend)\n",
        "pubs = [qc_isa]\n",
        "\n",
        "# Run the job on real quantum device\n",
        "\n",
        "job = sampler.run(pubs, shots=1000)\n",
        "res = job.result()\n",
        "counts = res[0].data.meas.get_counts()\n",
        "\n",
        "# OR run the job on the Aer simulator with noise model from real backend\n",
        "\n",
        "# job = sampler_sim.run([qc_isa])\n",
        "# res = job.result()\n",
        "# counts = res[0].data.meas.get_counts()\n",
        "\n",
        "# Step 4: Post-process\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "74008f89-5634-4e52-8061-87976888c39f",
      "metadata": {},
      "source": [
        "Esta pode ser um pouco mais surpreendente. Parece que o QFT do estado $|\\psi\\rangle = \\frac{1}{\\sqrt{2}} (|0\\rangle + |N/2\\rangle)$ é uma superposição de todos os estados de base uniforme. Mas se pensarmos em nossa visualização de cada estado da base $|\\phi_y\\rangle$ e em como a fase de cada componente gira em torno de $2\\pi$ $y$ vezes, então o motivo pelo qual chegamos a esse resultado pode ficar claro.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Verifique sua compreensão\n",
        "\n",
        "Usando a dica acima, explique por que o resultado que obtivemos para a Teoria Quântica dos Campos (QFT) de um $|\\psi\\rangle = \\frac{1}{\\sqrt{2}} (|0\\rangle + |N/2\\rangle)$ o é o esperado.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Resposta\">\n",
        "    O estado original tem uma fase relativa de 0 (ou um múltiplo inteiro de $2\\pi$ ) entre as duas partes da superposição. Portanto, sabemos que esse estado tem componentes de Fourier cujas fases também coincidem dessa forma: aqueles que têm 0 de mudança de fase entre o termo |0000> e o termo |1000>. Cada estado da base de Fourier $|\\phi_y\\rangle$ é composto de termos cuja fase se acumula a uma taxa de $2\\pi y/N$, o que significa que, quando ordenado da maneira usual, cada termo na superposição tem uma fase de $2\\pi y/N$ maior do que o termo anterior. Portanto, na metade do caminho $N/2$, queremos que a fase $2\\pi y/N * N/2$ seja um múltiplo inteiro de $2\\pi$. Isso acontece quando $y$ é par.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Que superposição de estados computacionais corresponderia a uma Teoria Quântica dos Campos com picos em todos os números binários ímpares?\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Resposta\">\n",
        "    Se você pegar o QFT do estado $\\psi = |0\\rangle - |N/2\\rangle$, verá picos em todos os estados com números binários ímpares.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "af84bf95-c211-4a58-a851-1e827a42fcdb",
      "metadata": {},
      "source": [
        "<span id=\"break-down-the-qft-algorithm\" />\n",
        "\n",
        "## Analise o algoritmo QFT\n",
        "\n",
        "Agora que adquirimos mais intuição sobre a relação entre os estados do qubit na base computacional e na base de Fourier, vamos nos aprofundar no próprio algoritmo QFT. Em outras palavras, quais portas realmente implementamos no computador quântico para realizar essa transformação?\n",
        "\n",
        "Vamos começar com um único qubit. Portanto, isso significa que teremos dois estados-base. A QFT $_2$ transforma os estados da base computacional $|0\\rangle$ e $|1\\rangle$ em estados da base de Fourier $\\phi_0$ e $\\phi_1$ :\n",
        "\n",
        "$|\\phi_0\\rangle = \\frac{1}{\\sqrt{2}}(|0\\rangle + |1\\rangle)$\n",
        "\n",
        "$|\\phi_1\\rangle = \\frac{1}{\\sqrt{2}}(|0\\rangle - |1\\rangle)$\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Verifique sua compreensão\n",
        "\n",
        "Use a equação da Teoria Quântica dos Campos (QFT) apresentada na seção anterior para verificar esses dois estados de base de Fourier acima.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Resposta\">\n",
        "    A fórmula geral da QFT é:\n",
        "\n",
        "    $ | \\phi_y \\rangle =  \\frac{1}{\\sqrt{N}}\\sum_{x=0}^{N-1}\\omega_N^{y x} \\vert x \\rangle$\n",
        "\n",
        "    Para um único qubit ( $n=1$ ), $N=2^n=2$, e $\\omega_N^{xy} = e^{2\\pi i \\frac {y x}{2}}$. Portanto, temos\n",
        "\n",
        "    $ | \\phi_0 \\rangle = \\frac{1}{\\sqrt{2}}(e^{2\\pi i \\frac {0 \\times 0}{2}}|0\\rangle + e^{2\\pi i \\frac {0 \\times 1}{2}}|1\\rangle) = \\frac{1}{\\sqrt{2}}(|0\\rangle + |1\\rangle)$\n",
        "\n",
        "    $ | \\phi_1 \\rangle = \\frac{1}{\\sqrt{2}}(e^{2\\pi i \\frac {1 \\times 0}{2}}|0\\rangle + e^{2\\pi i \\frac {1 \\times 1}{2}}|1\\rangle) = \\frac{1}{\\sqrt{2}}(|0\\rangle - |1\\rangle)$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Dê uma olhada nessas duas equações. Talvez você já conheça uma porta quântica que pode ser usada para implementar essa transformação. Ou seja, há uma porta que transforma os estados da base computacional $|0\\rangle$ e $|1\\rangle$ nos respectivos estados da base de Fourier $|\\phi_0\\rangle$ e $|\\phi_1\\rangle$. É uma porta Hadamard! Isso fica ainda mais claro se introduzirmos uma representação matricial da operação QFT $_N$ :\n",
        "\n",
        "$ \\text{QFT}_N = \\frac{1}{\\sqrt{N}} \\sum_{x=0}^{N-1} \\sum_{y=0}^{N-1} \\omega_N^{xy} \\vert x \\rangle \\langle y \\vert$\n",
        "\n",
        "Se você não estiver familiarizado com essa notação para expressar um operador quântico, não tem problema! É uma forma de representar uma matriz $N \\times N$, em que $x$ e $y$ indexam as colunas e as linhas da matriz, de $0$ a $N-1$, e $\\omega_N^{xy}$ é o valor dessa entrada específica. Portanto, a entrada na 0ª coluna e na 2ª linha, por exemplo, seria apenas $\\omega_N^{0,2} = e^{2 \\pi i \\frac{0 \\times 2}{N}} = 1$.\n",
        "\n",
        "Nessa representação, cada um dos estados da base computacional está associado a um dos vetores da base:\n",
        "\n",
        "$$|0\\rangle =\n",
        "\\begin{pmatrix}\n",
        "1 \\\\ 0 \\\\ \\vdots \\\\ 0\n",
        "\\end{pmatrix},\n",
        "|1\\rangle =\n",
        "\\begin{pmatrix}\n",
        "0 \\\\ 1 \\\\ \\vdots \\\\ 0\n",
        "\\end{pmatrix},\n",
        "|N-1\\rangle =\n",
        "\\begin{pmatrix}\n",
        "0 \\\\ 0 \\\\ \\vdots \\\\ 1\n",
        "\\end{pmatrix}.\n",
        "$$\n",
        "\n",
        "Se você quiser saber mais sobre essa representação, consulte a lição de John Watrous sobre sistemas múltiplos no curso Noções [básicas de informação quântica](/learning/courses/basics-of-quantum-information/multiple-systems/introduction).\n",
        "\n",
        "Vamos tentar construir a matriz para QFT $_4$. Usando a fórmula acima, descobrimos que\n",
        "\n",
        "$\\text{QFT}_4 = \\frac{1}{2} \\begin{pmatrix}     1 & 1 & 1 & 1 \\\\     1 & i & -1 & -i \\\\     1 & -1 & 1 & -1 \\\\     1 & -i & -1 & i \\\\ \\end{pmatrix} $\n",
        "\n",
        "Para implementar essa matriz em um computador quântico, precisaremos descobrir qual combinação de portas aplicadas a quais qubits nos dará uma transformação unitária que corresponda à matriz acima. Já conhecemos um dos portões que serão necessários: o Hadamard. Outra porta de que precisaremos é a porta de fase controlada, que aplica uma fase relativa $\\alpha$ ao estado do qubit de destino, desde que o qubit de controle esteja no estado $|1\\rangle$. Na forma de matriz, isso se parece com:\n",
        "\n",
        "$\\text{CP}_\\alpha = \\begin{pmatrix}     1 & 0 & 0 & 0 \\\\     0 & 1 & 0 & 0 \\\\     0 & 0 & 1 & 0 \\\\     0 & 0 & 0 & e^{i\\alpha} \\\\ \\end{pmatrix} $\n",
        "\n",
        "Como apenas o estado $|11\\rangle$ é alterado, na verdade não importa qual qubit é considerado o \"controle\" e qual é o \"alvo\" O resultado será o mesmo de qualquer maneira.\n",
        "\n",
        "Por fim, também precisaremos de alguns portões SWAP. Uma porta SWAP troca os estados de dois qubits. Parece que sim:\n",
        "\n",
        "$\\text{SWAP}_\\alpha = \\begin{pmatrix}     1 & 0 & 0 & 0 \\\\     0 & 0 & 1 & 0 \\\\     0 & 1 & 0 & 0 \\\\     0 & 0 & 0 & 1 \\\\ \\end{pmatrix} $\n",
        "\n",
        "O procedimento para construir um circuito QFT $_{2^m}$ nos qubits $m$ é iterativo: primeiro, você aplica a QFT $_{2^{m-1}}$ aos qubits $1$ a $m-1$ e, em seguida, adiciona algumas portas entre o qubit $0$ e os outros qubits $m-1$. Mas para aplicar a QFT $_{2^{m-1}}$, primeiro você precisa aplicar a QFT $_{2^{m-2}}$ aos qubits 2 a $m-1$ e, em seguida, adicionar algumas portas entre o qubit 1 e os qubits restantes $2$ a $m-1$. É como um ninho de bonecas russo: cada boneca acrescenta um fator de dois na dimensão do circuito QFT, com a menor boneca no centro, sendo a QFT $_2$, ou a porta Hadamard.\n",
        "\n",
        "Para colocar uma boneca dentro da boneca de tamanho maior seguinte, aumentando assim a dimensão do QFT por um fator de dois, você sempre segue o mesmo procedimento:\n",
        "\n",
        "1. Primeiro, aplique a QFT $_{2^{m-1}}$ aos qubits $m-1$ mais baixos. Essa é a sua \"boneca menor\" do conjunto de bonecas russas que você colocará dentro da próxima boneca maior.\n",
        "2. Use o próximo qubit acima como controle e aplique portas de fase controladas a cada um dos $m-1$ qubits inferiores, com fases para os estados de base padrão de cada um dos $m-1$ qubits restantes.\n",
        "3. Execute um Hadamard no mesmo qubit superior que foi usado como controle nas portas de fase.\n",
        "4. Use as portas SWAP para alterar a ordem dos qubits de modo que o bit menos significativo (superior) se torne o bit mais significativo (inferior) e todos os outros sejam deslocados para cima em um.\n",
        "\n",
        "Já usamos a função `QFTGate` da biblioteca de circuitos do Qiskit, mas agora vamos dar uma olhada em algumas dessas portas QFT para verificar o procedimento acima. Podemos fazer isso com `decompose()`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "6de41e8b-2900-4600-bd35-96df80b1b409",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/6de41e8b-2900-4600-bd35-96df80b1b409-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)\n",
        "qc.compose(QFTGate(1), inplace=True)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "066a1c6b-864e-4cf3-b9f1-2751b9b00998",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/066a1c6b-864e-4cf3-b9f1-2751b9b00998-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2)\n",
        "qc.compose(QFTGate(2), inplace=True)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "dffb70da-0107-4aeb-b433-20f4b82f6abf",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/dffb70da-0107-4aeb-b433-20f4b82f6abf-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(3)\n",
        "qc.compose(QFTGate(3), inplace=True)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "b3375193-b230-4dda-a676-ae350c3a9b93",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/computer-science/qft/extracted-outputs/b3375193-b230-4dda-a676-ae350c3a9b93-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 18,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(4)\n",
        "qc.compose(QFTGate(4), inplace=True)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "0f29ce85-e9a8-4445-b3ac-5625bdca9c8a",
      "metadata": {},
      "source": [
        "Portanto, esperamos que, a partir dos quatro primeiros QFTs, você possa começar a ver como cada um deles está aninhado dentro do próximo maior. Você deve ter notado, no entanto, que algumas das portas de fase não são exatamente como prescritas no procedimento que descrevemos acima, e os SWAPs não aparecem após cada sub-rotina, mas apenas no final do QFT completo. Isso nos poupa de portas desnecessárias, o que faria com que o circuito demorasse mais e fosse mais propenso a erros. Em vez de implementar o SWAP após cada boneco aninhado, o circuito mantém o controle de onde cada estado de qubit *deve* estar e ajusta os qubits aos quais está aplicando as portas de fase de acordo. Em seguida, um conjunto final de SWAPs no final coloca tudo em seu devido lugar.\n",
        "\n",
        "<span id=\"apply-the-qft-phase-estimation\" />\n",
        "\n",
        "## Aplique o QFT: Estimativa de fase\n",
        "\n",
        "Vamos ver como a QFT pode ser usada para resolver um problema útil na computação quântica. O cálculo da transformada quântica inversa de Fourier é uma etapa necessária em um algoritmo conhecido como Estimativa de Fase Quântica (QPE), que é, por sua vez, uma sub-rotina em muitos outros algoritmos, incluindo a \"joia da coroa\" dos algoritmos quânticos, o algoritmo de fatoração de Shor.\n",
        "\n",
        "O objetivo do QPE é estimar os valores próprios de um operador unitário. Os operadores unitários são onipresentes na computação quântica e, muitas vezes, encontrar os valores próprios de seus vetores próprios associados é uma etapa necessária em um algoritmo maior. Dependendo do problema, um valor próprio pode representar uma energia de um Hamiltoniano em um problema do tipo simulação, pode nos ajudar a encontrar fatores primos de um número no algoritmo de Shor ou pode conter outras informações essenciais. O QPE é uma das subrotinas mais importantes e amplamente usadas na computação quântica.\n",
        "\n",
        "Então, o que isso tem a ver com uma transformada quântica de Fourier? Bem, como você deve se lembrar, qualquer valor próprio $\\lambda$ de um operador unitário tem uma magnitude $|\\lambda| = 1$. Portanto, podemos escrever cada valor próprio como um número complexo com magnitude um:\n",
        "\n",
        "$\\lambda = e^{2\\pi i \\theta}$\n",
        "\n",
        "em que $\\theta$ é um número real entre 0 e 1. Se você quiser mais informações sobre matrizes unitárias, veja [a lição de John Watrous sobre o assunto](/learning/courses/basics-of-quantum-information/multiple-systems/quantum-information) em Noções básicas de informação quântica.\n",
        "\n",
        "Observe que $\\lambda$ é *periódico* em $\\theta$. Isso já pode lhe sugerir que uma QFT pode estar envolvida, pois vimos como as QFTs são úteis para analisar funções periódicas. A seguir, examinaremos o algoritmo e veremos exatamente como a QFT entra em ação.\n",
        "\n",
        "<span id=\"how-qpe-works\" />\n",
        "\n",
        "### Como funciona o QPE\n",
        "\n",
        "Primeiro, começaremos com o algoritmo QPE mais simples, que estima aproximadamente a fase com um único dígito binário de precisão. Em outras palavras, esse algoritmo pode distinguir entre $\\theta = 0 $ e $\\theta = 1/2$, mas não pode fazer melhor do que isso. Aqui está o diagrama do circuito:\n",
        "\n",
        "![Diagrama de circuito do algoritmo QPE para um único qubit de dados. Um Hadamard é aplicado ao qubit de dados. Em seguida, o algoritmo usa outro qubit auxiliar, no qual é aplicada uma porta U controlada, com o qubit de dados como controle. Depois de outro Hadamard no qubit 0, os qubits são medidos.](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/QPE1qubit.avif)\n",
        "\n",
        "Os qubits são preparados no estado $|\\pi_0\\rangle = |\\psi\\rangle|0\\rangle$, em que o qubit $0$ está no estado $|0\\rangle$ e os qubits restantes estão no estado $|\\psi\\rangle$, que é um estado próprio de $U$. Após o primeiro Hadamard, o estado do qubit se torna:\n",
        "\n",
        "$|\\pi_1\\rangle = \\frac{1}{\\sqrt{2}}|\\psi\\rangle (|0\\rangle + |1\\rangle)$\n",
        "\n",
        "O próximo portão é um portão \"controlado - $U$ \". Isso aplica a operação unitária $U$ aos qubits inferiores que estão no estado $|\\psi\\rangle$ se o qubit 0 estiver no estado $|1\\rangle$, mas não faz nada para $|\\psi\\rangle$ se o qubit 0 estiver no estado $|0\\rangle$. Isso transforma os qubits no estado:\n",
        "\n",
        "$|\\pi_2\\rangle = \\frac{1}{\\sqrt{2}}( |\\psi\\rangle|0\\rangle + e^{2\\pi i \\theta}|\\psi\\rangle|1\\rangle)$\n",
        "$=  \\frac{1}{\\sqrt{2}}|\\psi\\rangle (|0\\rangle + e^{2\\pi i \\theta}|1\\rangle)$\n",
        "\n",
        "Algo estranho acabou de acontecer: a porta controlled- $U$ usa apenas o qubit $0$ como qubit de controle, portanto, pode-se pensar que essa porta não alteraria o estado do qubit 0. Mas, de alguma forma, isso acontece! Embora a operação tenha sido aplicada aos qubits inferiores, o efeito geral da porta é alterar a fase do qubit $0$. Isso é conhecido como \"mecanismo de retrocesso de fase\" e é usado em muitos algoritmos quânticos, incluindo os algoritmos de Deutsch-Josza e Grover. Se você quiser saber mais sobre o mecanismo de phase-kickback, consulte a lição de John Watrous sobre [algoritmos de consulta quântica](/learning/courses/fundamentals-of-quantum-algorithms/quantum-query-algorithms/deutsch-algorithm) em Fundamentos de algoritmos quânticos.\n",
        "\n",
        "Após a fase-kickback, aplicamos mais um Hadamard ao qubit $0$, o que resulta no estado:\n",
        "\n",
        "$|\\pi_3\\rangle = |\\psi\\rangle ( \\frac{1+e^{2\\pi i \\theta}}{2} |0\\rangle + \\frac{1 - e^{2\\pi i \\theta}}{2}|1\\rangle) = |\\psi\\rangle ( \\cos(\\pi\\theta) |0\\rangle - i \\sin(\\pi\\theta)|1\\rangle)$\n",
        "\n",
        "Portanto, quando medirmos o qubit $0$ no final, mediremos $|0\\rangle$ com 100% de certeza se for $\\theta = 0$ e mediremos $|1\\rangle$ com 100% de certeza se for $\\theta = \\frac{1}{2}$ (e se nosso computador quântico for perfeito, sem ruído). Se $\\theta$ for algo diferente disso, a medição final será apenas probabilística e nos dirá apenas uma parte.\n",
        "\n",
        "<span id=\"qpe-with-more-precision-more-qubits\" />\n",
        "\n",
        "### QPE com mais precisão: mais qubits\n",
        "\n",
        "Podemos estender esse conceito simples a um algoritmo mais complicado com precisão arbitrária. Se, em vez de usar apenas o qubit $0$ para medir a fase, usarmos os qubits $m$ $0$ a $m-1$, poderemos estimar a fase com $m$ bits de precisão. Vamos ver como isso funciona:\n",
        "\n",
        "![Diagrama de circuito do algoritmo QPE para vários qubits. Os Hadamards são aplicados aos qubits de dados de 0 a m-1. Em seguida, uma série de portas controladas-U é aplicada aos m qubits auxiliares. Por fim, uma QFT inversa é aplicada aos qubits e eles são medidos.](https://quantum.cloud.ibm.com/learning/images/modules/computer-science/qft/QPE_withpi.avif)\n",
        "\n",
        "Esse circuito QPE mais preciso começa da mesma forma que a versão de bit único: Hadamards são aplicados aos primeiros $m$ qubits, e os qubits restantes são preparados no estado $|\\psi\\rangle$, criando o estado:\n",
        "\n",
        "$|\\pi_1\\rangle = \\frac{1}{2^{m/2}}|\\psi\\rangle(|0\\rangle+|1\\rangle)(|0\\rangle+|1\\rangle)...(|0\\rangle+|1\\rangle)$\n",
        "\n",
        "Agora, os unitários controlados são aplicados. O Qubit $0$ é o controle para o mesmo $U$ unitário de antes. Mas agora, o qubit $1$ é o controle para o unitário $U^2$, que é simplesmente $U$ aplicado duas vezes. Portanto, o autovalor de $U^2$ é $e^{2*2\\pi i \\theta}$. Em geral, cada qubit $k$ de 0 a $m-1$ será o controle do unitário $U^{2^k}$. Isso significa que cada um desses qubits sofrerá um retorno de fase de $e^{2^k*2\\pi i \\theta}$. Isso resulta no estado:\n",
        "\n",
        "$|\\pi_2\\rangle = |\\psi\\rangle \\otimes \\frac{1}{2^{m/2}} (|0\\rangle+e^{2^{m-1}2\\pi i \\theta}|1\\rangle)(|0\\rangle+e^{2^{m-2}2\\pi i \\theta}|1\\rangle)...(|0\\rangle+e^{2\\pi i \\theta}|1\\rangle)$\n",
        "\n",
        "Isso pode ser reescrito como uma soma dos estados da base computacional:\n",
        "\n",
        "$|\\pi_2\\rangle = |\\psi\\rangle \\otimes \\frac{1}{2^{m/2}} \\sum_{k=0}^{2^{m}-1} e^{2\\pi i k \\theta} |k\\rangle $\n",
        "\n",
        "A soma parece familiar? É um QFT! Lembre-se da equação de uma transformada quântica de Fourier:\n",
        "\n",
        "$ \\text{QFT}_{2^m}| y \\rangle =  \\frac{1}{\\sqrt{2^m}}\\sum_{x=0}^{2^m-1}\\omega_{2^m}^{y x} \\vert x \\rangle$\n",
        "\n",
        "Portanto, se a fase $\\theta = y/2^m$ para algum número inteiro $y$ entre $0$ e $2^m-1$, então a QFT inversa desse estado resultará no estado:\n",
        "\n",
        "$|\\pi_3\\rangle = |\\psi\\rangle \\otimes |y\\rangle $\n",
        "\n",
        "e a partir de $|y\\rangle$, podemos deduzir $\\theta$.\n",
        "\n",
        "No entanto, se $\\theta/2^m$ *não* for um múltiplo inteiro, a aplicação da QFT inversa apenas *aproximará* $\\theta$. O grau de aproximação de $\\theta$ será probabilístico, o que significa que nem sempre obteremos a melhor aproximação, mas ela será bem próxima, e quanto mais qubits $m$ você usar, melhor será a aproximação. Para saber como quantificar essa aproximação de $\\theta$, confira a lição de John Watrous sobre [Estimativa de fase e fatoração](/learning/courses/fundamentals-of-quantum-algorithms/phase-estimation-and-factoring/phase-estimation-procedure) em Fundamentos de algoritmos quânticos.\n",
        "\n",
        "<span id=\"conclusion\" />\n",
        "\n",
        "### Conclusão\n",
        "\n",
        "Este módulo apresentou uma visão geral do que é um QFT, como ele é implementado em um computador quântico e como ele pode ser útil na solução de problemas. Demos a você uma amostra de sua utilidade quando vimos como ele pode ser usado na estimativa de fase quântica para aprender sobre os valores próprios de uma matriz unitária.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "33b2c0e7-b48a-4426-8472-ad9a52bf48ea",
      "metadata": {},
      "source": [
        "<span id=\"critical-concepts\" />\n",
        "\n",
        "### Conceitos críticos\n",
        "\n",
        "* A Transformada Quântica de Fourier é o análogo quântico da Transformada Discreta de Fourier.\n",
        "* A QFT é um exemplo de uma transformação de base.\n",
        "* O procedimento de estimativa de fase quântica se baseia no mecanismo de retrocesso de fase das operações unitárias controladas, bem como em uma QFT inversa.\n",
        "* A QFT e a QPE são sub-rotinas amplamente usadas em vários algoritmos quânticos.\n",
        "\n",
        "<span id=\"questions\" />\n",
        "\n",
        "## Perguntas\n",
        "\n",
        "<span id=\"true/false\" />\n",
        "\n",
        "### Verdadeiro/Falso\n",
        "\n",
        "1. T/F A transformada quântica de Fourier é o análogo quântico da transformada clássica discreta de Fourier (DFT).\n",
        "2. O T/F QFT pode ser implementado usando apenas portas Hadamard e CNOT.\n",
        "3. T/F A QFT é um componente essencial do algoritmo de Shor.\n",
        "4. T/F O resultado da Estimativa de Fase Quântica é um estado quântico que representa o vetor próprio do operador.\n",
        "5. T/F O QPE requer o uso da Transformada Quântica de Fourier inversa (QFT $^\\dag$ ).\n",
        "6. T/F No QPE, se a fase $\\phi$ for exatamente representável com $n$ bits, o algoritmo fornecerá o resultado correto com probabilidade 1.\n",
        "\n",
        "<span id=\"short-answers\" />\n",
        "\n",
        "### Respostas curtas\n",
        "\n",
        "1. Quantos qubits são necessários para realizar um QFT em um sistema com $2^n$ pontos de dados?\n",
        "2. A QFT pode ser usada em um estado que não seja um estado de base computacional? Em caso afirmativo, o que acontece?\n",
        "3. Como o número de qubits de controle usados no QPE afeta a resolução da estimativa de fase resultante?\n",
        "\n",
        "<span id=\"problems\" />\n",
        "\n",
        "### Problemas\n",
        "\n",
        "1. Use a multiplicação de matrizes para verificar se as etapas do algoritmo QFT de fato resultam na matriz $\\text{QFT}_4$ :\n",
        "\n",
        "$$\n",
        "\\text{QFT}_4 = \\frac{1}{2}\n",
        "\\begin{pmatrix}\n",
        "    1 & 1 & 1 & 1 \\\\\n",
        "    1 & i & -1 & -i \\\\\n",
        "    1 & -1 & 1 & -1 \\\\\n",
        "    1 & -i & -1 & i \\\\\n",
        "\\end{pmatrix}\n",
        "$$\n",
        "\n",
        "(Não é necessário fazer isso à mão!)\n",
        "\n",
        "<span id=\"challenge-problems\" />\n",
        "\n",
        "### Problemas desafiadores\n",
        "\n",
        "1. Crie um estado de quatro qubits que seja uma superposição igual de todas as bases computacionais ímpares: $|\\psi\\rangle = |0001\\rangle + |0011\\rangle + |0101\\rangle + |0111\\rangle +|1001\\rangle +|1011\\rangle +|1101\\rangle +|1111\\rangle$. Em seguida, execute uma QFT no estado. Qual é o estado resultante? Explique por que seu resultado faz sentido, usando seu conhecimento de transformadas de Fourier.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "in_page_toc_max_heading_level": 2,
    "in_page_toc_min_heading_level": 2,
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    },
    "hours": 2
  },
  "nbformat": 4,
  "nbformat_minor": 5
}