{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "8fe3ca32",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Hardware\"\n",
        "description: \"Esta lição explora o hardware moderno de computação quântica. É baseado em um curso presencial ministrado na Universidade de Tóquio.\"\n",
        "---\n",
        "\n",
        "<span id=\"hardware\" />\n",
        "\n",
        "# Hardware\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Masao Tokunari e Tamiya Onodera (14 de junho de 2024)\n",
        "\n",
        "  Este curso é baseado em um curso ao vivo ministrado na Universidade de Tóquio.\n",
        "\n",
        "  O pdf da palestra desta lição foi dividido em duas partes. [Faça o download da parte 1](https://ibm.ent.box.com/public/static/ruz8wf353hncenmaywjlfjilflaumnzt.zip) e [da parte 2](https://ibm.ent.box.com/public/static/tg8vv00ern2bmxmm033xt9oe0fcvwamc.zip). Observe que alguns trechos de código podem se tornar obsoletos, pois são imagens estáticas.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e0cf0747",
      "metadata": {},
      "source": [
        "<span id=\"1-introduction\" />\n",
        "\n",
        "## 1. Introdução\n",
        "\n",
        "Esta lição explora o hardware moderno de computação quântica.\n",
        "\n",
        "Começaremos verificando algumas versões e importando alguns pacotes relevantes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "798d0ab4-34f5-4c64-83f0-02ef5149e6f3",
      "metadata": {},
      "outputs": [],
      "source": [
        "import statistics\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2cc2f2a3-947f-439b-b683-911539f1e6f2",
      "metadata": {},
      "source": [
        "<span id=\"2-backend-and-target\" />\n",
        "\n",
        "## 2. Backend e Destino\n",
        "\n",
        "O Qiskit fornece uma API para obter as informações, tanto estáticas quanto dinâmicas, sobre um dispositivo quântico. Usamos uma instância de backend para fazer a interface com um dispositivo, que inclui uma instância de destino, um modelo de máquina abstrato que resume os recursos pertinentes, como sua arquitetura de conjunto de instruções (ISA) e quaisquer propriedades ou restrições associadas a ela.\n",
        "Vamos usar essas instâncias de back-end para obter algumas das informações que você vê na página [Compute resources (Recursos de computação)](/computers) em IBM Quantum® Platform.   Primeiro, criamos uma instância de backend para um dispositivo de interesse.  A seguir, escolhemos \"ibm\\_kyoto\", \"ibm\\_kawasaki\" ou a máquina Eagle menos ocupada. Seu acesso às QPUs pode ser diferente; atualize o nome do backend de acordo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b92ad1bf-6ad4-420c-8a3a-5bfc488d5923",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'ibm_strasbourg'"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "service = QiskitRuntimeService()\n",
        "# backend = service.backend(\"ibm_kawasaki\") # an Eagle, if you have access to ibm_kawasaki\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")  # Eagle\n",
        "backend.name"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c082da02-fcc5-4506-b4fe-9015e99e63dc",
      "metadata": {},
      "source": [
        "Começamos com algumas informações básicas (estáticas) sobre o dispositivo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "33c39786-d44a-47bb-8245-72eb6b97e394",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "ibm_strasbourg, 127 qubits\n",
            "processor type = {'family': 'Eagle', 'revision': 3} \n",
            "basis gates = ['ecr', 'id', 'rz', 'sx', 'x']\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(\n",
        "    f\"\"\"\n",
        "{backend.name}, {backend.num_qubits} qubits\n",
        "processor type = {backend.processor_type}\n",
        "basis gates = {backend.basis_gates}\n",
        "\"\"\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "31675447-1a26-4168-a038-09cc7535e037",
      "metadata": {},
      "source": [
        "<span id=\"21-exercise\" />\n",
        "\n",
        "### 2.1 Exercício\n",
        "\n",
        "Tente obter as informações básicas sobre um dispositivo Heron, \"ibm\\_strasbourg\". Tente fazer isso por conta própria, mas o código foi adicionado abaixo para que você mesmo possa verificar.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f29afd7e-af40-4cd5-bc0e-a864663a616d",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "ibm_strasbourg, 133 qubits\n",
            "processor type = {'family': 'Heron', 'revision': '1'} \n",
            "basis gates = ['cz', 'id', 'rz', 'sx', 'x']\n",
            "\n"
          ]
        }
      ],
      "source": [
        "a_heron = service.backend(\"ibm_strasbourg\")  # a Heron\n",
        "\n",
        "# your code here\n",
        "print(\n",
        "    f\"\"\"\n",
        "{backend.name}, {a_heron.num_qubits} qubits\n",
        "processor type = {a_heron.processor_type}\n",
        "basis gates = {a_heron.basis_gates}\n",
        "\"\"\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "08fef064-3fc6-4c27-9288-a2e3aa7f5d08",
      "metadata": {},
      "source": [
        "<span id=\"22-coupling-map\" />\n",
        "\n",
        "### 2.2 Mapa de acoplamento\n",
        "\n",
        "Agora, desenhamos o mapa de acoplamento do dispositivo. Como você pode ver, os nós são qubits numerados. As bordas indicam pares aos quais você pode aplicar diretamente a porta de entrelaçamento de 2 qubits.  A topologia é chamada de \"heavy-hex lattice\".\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "51b87458-a5e8-4e77-a34d-39fe425a5f01",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/hardware/extracted-outputs/51b87458-a5e8-4e77-a34d-39fe425a5f01-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# This function requires that Graphviz is installed. If you need to install Graphviz\n",
        "# you can refer to:\n",
        "# https://graphviz.org/download/#executable-packages for instructions.\n",
        "try:\n",
        "    fig = backend.coupling_map.draw()\n",
        "except RuntimeError as ex:\n",
        "    print(ex)\n",
        "fig"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "881a5350-282c-4a89-b9e2-ac6bf61c6571",
      "metadata": {},
      "source": [
        "<span id=\"3-qubit-properties\" />\n",
        "\n",
        "## 3. Propriedades do qubit\n",
        "\n",
        "O dispositivo Eagle tem 127 qubits.   Vamos obter as propriedades de alguns deles.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "9bcb9ce2-5ea8-487b-a7ac-a2956e8cbc34",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0: QubitProperties(t1=0.000183686508736532, t2=0.00023613944465408068, frequency=4832100227.116953)\n",
            "1: QubitProperties(t1=0.00048794378526038294, t2=9.007098375327869e-05, frequency=4736264354.075363)\n",
            "2: QubitProperties(t1=0.00021247781834456527, t2=7.81037910324034e-05, frequency=4859349851.150393)\n",
            "3: QubitProperties(t1=0.0002936462084765663, t2=0.00011400214529510604, frequency=4679749549.503852)\n",
            "4: QubitProperties(t1=0.00044229440258559125, t2=0.0003181648356339447, frequency=4845872064.050596)\n"
          ]
        }
      ],
      "source": [
        "for qn in range(backend.num_qubits):\n",
        "    if qn >= 5:\n",
        "        break\n",
        "    print(f\"{qn}: {backend.qubit_properties(qn)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be601762",
      "metadata": {},
      "source": [
        "Vamos calcular a mediana dos tempos de T1 dos qubits.   Compare o resultado com o mostrado para o dispositivo na [IBM Quantum Platform.](/)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "e8f398b2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Median T1: 285.43 μs'"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "t1s = [backend.qubit_properties(qq).t1 for qq in range(backend.num_qubits)]\n",
        "f\"Median T1: {(statistics.median(t1s)*10**6):.2f} \\u03bcs\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "01695904-2cb2-4f1d-9396-82cc94429d81",
      "metadata": {},
      "source": [
        "<span id=\"31-exercise\" />\n",
        "\n",
        "### 3.1 Exercício\n",
        "\n",
        "Por favor, calcule a mediana dos tempos de T2 dos qubits. Tente fazer isso por conta própria, mas o código foi adicionado abaixo para que você mesmo possa verificar.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "49fbe7a4-3dea-442f-ae3f-e82df93d406a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Median T2: 173.10 μs'"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Your code here\n",
        "\n",
        "t2s = [backend.qubit_properties(qq).t2 for qq in range(backend.num_qubits)]\n",
        "f\"Median T2: {(statistics.median(t2s)*10**6):.2f} \\u03bcs\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7bdf8873-359e-4b03-98af-ede989a4a96d",
      "metadata": {},
      "source": [
        "<span id=\"32-gate-and-readout-errors\" />\n",
        "\n",
        "### 3.2 Erros de porta e leitura\n",
        "\n",
        "Passamos agora aos erros de porta. Para começar, estudamos a estrutura de dados da instância de destino. É um dicionário cujas chaves são nomes de operações.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "c9188662",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "dict_keys(['measure', 'id', 'sx', 'delay', 'x', 'for_loop', 'rz', 'if_else', 'ecr', 'reset', 'switch_case'])"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "target = backend.target\n",
        "target.keys()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "46e3a8ac-65dc-4973-bd72-820676727f4e",
      "metadata": {},
      "source": [
        "Seus valores também são dicionários.  Vejamos alguns dos itens do valor (dicionário) da operação 'sx'.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "c9b30ede-c00f-4e18-bb72-3bfc06e6afa5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0 (0,) InstructionProperties(duration=6e-08, error=0.0007401311759115297)\n",
            "1 (1,) InstructionProperties(duration=6e-08, error=0.0003163759907528654)\n",
            "2 (2,) InstructionProperties(duration=6e-08, error=0.0003183859004638003)\n",
            "3 (3,) InstructionProperties(duration=6e-08, error=0.00042235914178831863)\n",
            "4 (4,) InstructionProperties(duration=6e-08, error=0.011163151923589715)\n"
          ]
        }
      ],
      "source": [
        "for i, qq in enumerate(target[\"sx\"]):\n",
        "    if i >= 5:\n",
        "        break\n",
        "    print(i, qq, target[\"sx\"][qq])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a322b40-bbf0-4b54-a151-9ba52f7bffe1",
      "metadata": {},
      "source": [
        "Vamos fazer o mesmo com as operações \"ecr\" e \"measure\".\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "f9cac843-4789-4ca3-84bd-0a4c165820a9",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0 (0, 14) InstructionProperties(duration=6.6e-07, error=0.01486295709788732)\n",
            "1 (1, 0) InstructionProperties(duration=6.6e-07, error=0.015201590794522601)\n",
            "2 (2, 1) InstructionProperties(duration=6.6e-07, error=0.00697838102630724)\n",
            "3 (2, 3) InstructionProperties(duration=6.6e-07, error=0.008075067943986797)\n",
            "4 (3, 4) InstructionProperties(duration=6.6e-07, error=0.0630164507876913)\n"
          ]
        }
      ],
      "source": [
        "for i, edge in enumerate(target[\"ecr\"]):\n",
        "    if i >= 5:\n",
        "        break\n",
        "    print(i, edge, target[\"ecr\"][edge])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "af36138a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0 (0,) InstructionProperties(duration=1.6e-06, error=0.0078125)\n",
            "1 (1,) InstructionProperties(duration=1.6e-06, error=0.155029296875)\n",
            "2 (2,) InstructionProperties(duration=1.6e-06, error=0.057373046875)\n",
            "3 (3,) InstructionProperties(duration=1.6e-06, error=0.02880859375)\n",
            "4 (4,) InstructionProperties(duration=1.6e-06, error=0.01318359375)\n"
          ]
        }
      ],
      "source": [
        "for i, qq in enumerate(target[\"measure\"]):\n",
        "    if i >= 5:\n",
        "        break\n",
        "    print(i, qq, target[\"measure\"][qq])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5d0c106a-3641-42ed-9230-7dc6dbd47252",
      "metadata": {},
      "source": [
        "Como você pode ver, os erros de leitura tendem a ser maiores do que os da operação de 2 qubits, que, por sua vez, tendem a ser maiores do que os da operação de 1 qubit.\n",
        "\n",
        "Depois de entender as estruturas de dados, estamos prontos para calcular os erros medianos para as portas \"sx\" e \"ecr\". Novamente, compare os resultados com os mostrados para o dispositivo na [IBM Quantum Platform.](/)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "b239d726",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Median SX error: 2.277e-04'"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "sx_errors = [inst_prop.error for inst_prop in target[\"sx\"].values()]\n",
        "f\"Median SX error: {(statistics.median(sx_errors)):.3e}\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "8003f34b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Median ECR error: 6.895e-03'"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ecr_errors = [inst_prop.error for inst_prop in target[\"ecr\"].values()]\n",
        "f\"Median ECR error: {(statistics.median(ecr_errors)):.3e}\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "695ee4bd",
      "metadata": {},
      "source": [
        "<span id=\"4-appendix\" />\n",
        "\n",
        "## 4. Apêndice\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b538e8b5",
      "metadata": {},
      "source": [
        "Um recurso popular do Qiskit é sua capacidade de visualização. Ele inclui visualizadores de circuitos, visualizadores de estado e distribuição e visualizador de alvos.   Você já usou os dois primeiros nos notebooks anteriores do jupyter.   Vamos usar alguns recursos do visualizador de destino.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "97fead46",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/hardware/extracted-outputs/97fead46-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_gate_map\n",
        "\n",
        "plot_gate_map(backend, font_size=14)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "c9e05530",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/hardware/extracted-outputs/c9e05530-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_error_map\n",
        "\n",
        "plot_error_map(backend)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "22a48124-e6b4-4144-bee1-f01fa4c7ccbb",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'2.0.2'"
            ]
          },
          "execution_count": 24,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Check Qiskit version\n",
        "import qiskit\n",
        "\n",
        "qiskit.__version__"
      ]
    },
    {
      "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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}