{
  "cells": [
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "f5d21946",
      "metadata": {
        "slideshow": {
          "slide_type": "-"
        }
      },
      "source": [
        "---\n",
        "title: \"Códigos de repetición\"\n",
        "description: \"Este tutorial muestra cómo construir códigos de repetición básicos utilizando circuitos dinámicos de IBM, un ejemplo de corrección de errores cuánticos (QEC) básica.\"\n",
        "---\n",
        "\n",
        "<span id=\"repetition-codes\" />\n",
        "\n",
        "# Códigos de repetición\n",
        "\n",
        "*Estimación de uso: menos de 1 minuto en un procesador Heron (NOTA: Esto es sólo una estimación. Su tiempo de ejecución puede variar)*\n",
        "\n",
        "<span id=\"background\" />\n",
        "\n",
        "## En segundo plano\n",
        "\n",
        "Para permitir la corrección cuántica de errores (QEC) en tiempo real, es necesario poder controlar dinámicamente el flujo de programas cuánticos durante la ejecución, de modo que las puertas cuánticas puedan condicionarse a los resultados de las mediciones. Este tutorial ejecuta el código bit-flip, que es una forma muy simple de QEC. Demuestra un circuito cuántico dinámico que puede proteger un qubit codificado de un único error de salto de bit y, a continuación, evalúa el rendimiento del código de salto de bit.\n",
        "\n",
        "Puede explotar qubits ancilla adicionales y el entrelazamiento para medir *estabilizadores* que no transforman la información cuántica codificada, al tiempo que le informan de algunas clases de errores que podrían haberse producido. Un código estabilizador cuántico codifica $k$ qubits lógicos en $n$ qubits físicos. Los códigos estabilizadores se centran críticamente en la corrección de un conjunto de errores discretos con apoyo del grupo de Pauli $\\Pi^n$.\n",
        "\n",
        "Para obtener más información sobre la [corre](https://arxiv.org/abs/0905.2794) cción de errores cuánticos, consulta «Corrección de errores cuánticos para principiantes».\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "88672bd6",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## Requisitos\n",
        "\n",
        "Antes de empezar este tutorial, asegúrate de que tienes instalado lo siguiente:\n",
        "\n",
        "* Qiskit SDK v2.0 o posterior, con soporte [de visualización](/docs/api/qiskit/visualization)\n",
        "* Qiskit Runtime v0.40 o posterior (`pip install qiskit-ibm-runtime`)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "14c29e8b",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Configuración\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "1b9fd8ad",
      "metadata": {
        "slideshow": {
          "slide_type": "-"
        }
      },
      "outputs": [],
      "source": [
        "# Qiskit imports\n",
        "from qiskit import (\n",
        "    QuantumCircuit,\n",
        "    QuantumRegister,\n",
        "    ClassicalRegister,\n",
        ")\n",
        "\n",
        "# Qiskit Runtime\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler\n",
        "\n",
        "from qiskit_ibm_runtime.circuit import MidCircuitMeasure\n",
        "\n",
        "service = QiskitRuntimeService()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4d01e8d3",
      "metadata": {},
      "source": [
        "<span id=\"step-1-map-classical-inputs-to-a-quantum-problem\" />\n",
        "\n",
        "## Paso 1. Asignar entradas clásicas a un problema cuántico\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cdee0b18",
      "metadata": {},
      "source": [
        "<span id=\"build-a-bit-flip-stabilizer-circuit\" />\n",
        "\n",
        "### Construir un circuito estabilizador de inversión de bits\n",
        "\n",
        "El código de inversión de bits es uno de los ejemplos más sencillos de código estabilizador. Protege el estado contra un único error de cambio de bit (X) en cualquiera de los qubits de codificación. Consideremos la acción del error de cambio de bit $X$, que mapea $|0\\rangle \\rightarrow |1\\rangle$ y $|1\\rangle \\rightarrow |0\\rangle$ en cualquiera de nuestros qubits, entonces tenemos $\\epsilon = \\{E_0, E_1, E_2 \\} = \\{IIX, IXI, XII\\}$. El código requiere cinco qubits: tres se usan para codificar el estado protegido, y los dos restantes se usan como auxiliares de medida del estabilizador.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b588703a",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Choose the least busy backend that supports `measure_2`.\n",
        "\n",
        "backend = service.least_busy(\n",
        "    filters=lambda b: \"measure_2\" in b.supported_instructions,\n",
        "    operational=True,\n",
        "    simulator=False,\n",
        "    dynamic_circuits=True,\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "606dff18",
      "metadata": {},
      "outputs": [],
      "source": [
        "qreg_data = QuantumRegister(3)\n",
        "qreg_measure = QuantumRegister(2)\n",
        "creg_data = ClassicalRegister(3, name=\"data\")\n",
        "creg_syndrome = ClassicalRegister(2, name=\"syndrome\")\n",
        "state_data = qreg_data[0]\n",
        "ancillas_data = qreg_data[1:]\n",
        "\n",
        "\n",
        "def build_qc():\n",
        "    \"\"\"Build a typical error correction circuit\"\"\"\n",
        "    return QuantumCircuit(qreg_data, qreg_measure, creg_data, creg_syndrome)\n",
        "\n",
        "\n",
        "def initialize_qubits(circuit: QuantumCircuit):\n",
        "    \"\"\"Initialize qubit to |1>\"\"\"\n",
        "    circuit.x(qreg_data[0])\n",
        "    circuit.barrier(qreg_data)\n",
        "    return circuit\n",
        "\n",
        "\n",
        "def encode_bit_flip(circuit, state, ancillas) -> QuantumCircuit:\n",
        "    \"\"\"Encode bit-flip. This is done by simply adding a cx\"\"\"\n",
        "    for ancilla in ancillas:\n",
        "        circuit.cx(state, ancilla)\n",
        "    circuit.barrier(state, *ancillas)\n",
        "    return circuit\n",
        "\n",
        "\n",
        "def measure_syndrome_bit(circuit, qreg_data, qreg_measure, creg_measure):\n",
        "    \"\"\"\n",
        "    Measure the syndrome by measuring the parity.\n",
        "    We reset our ancilla qubits after measuring the stabilizer\n",
        "    so we can reuse them for repeated stabilizer measurements.\n",
        "    Because we have already observed the state of the qubit,\n",
        "    we can write the conditional reset protocol directly to\n",
        "    avoid another round of qubit measurement if we used\n",
        "    the `reset` instruction.\n",
        "    \"\"\"\n",
        "    circuit.cx(qreg_data[0], qreg_measure[0])\n",
        "    circuit.cx(qreg_data[1], qreg_measure[0])\n",
        "    circuit.cx(qreg_data[0], qreg_measure[1])\n",
        "    circuit.cx(qreg_data[2], qreg_measure[1])\n",
        "    circuit.barrier(*qreg_data, *qreg_measure)\n",
        "    circuit.append(MidCircuitMeasure(), [qreg_measure[0]], [creg_measure[0]])\n",
        "    circuit.append(MidCircuitMeasure(), [qreg_measure[1]], [creg_measure[1]])\n",
        "\n",
        "    with circuit.if_test((creg_measure[0], 1)):\n",
        "        circuit.x(qreg_measure[0])\n",
        "    with circuit.if_test((creg_measure[1], 1)):\n",
        "        circuit.x(qreg_measure[1])\n",
        "    circuit.barrier(*qreg_data, *qreg_measure)\n",
        "    return circuit\n",
        "\n",
        "\n",
        "def apply_correction_bit(circuit, qreg_data, creg_syndrome):\n",
        "    \"\"\"We can detect where an error occurred and correct our state\"\"\"\n",
        "    with circuit.if_test((creg_syndrome, 3)):\n",
        "        circuit.x(qreg_data[0])\n",
        "    with circuit.if_test((creg_syndrome, 1)):\n",
        "        circuit.x(qreg_data[1])\n",
        "    with circuit.if_test((creg_syndrome, 2)):\n",
        "        circuit.x(qreg_data[2])\n",
        "    circuit.barrier(qreg_data)\n",
        "    return circuit\n",
        "\n",
        "\n",
        "def apply_final_readout(circuit, qreg_data, creg_data):\n",
        "    \"\"\"Read out the final measurements\"\"\"\n",
        "    circuit.barrier(qreg_data)\n",
        "    circuit.measure(qreg_data, creg_data)\n",
        "    return circuit"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "dbe02949",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/repetition-codes/extracted-outputs/dbe02949-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/repetition-codes/extracted-outputs/dbe02949-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "def build_error_correction_sequence(apply_correction: bool) -> QuantumCircuit:\n",
        "    circuit = build_qc()\n",
        "    circuit = initialize_qubits(circuit)\n",
        "    circuit = encode_bit_flip(circuit, state_data, ancillas_data)\n",
        "    circuit = measure_syndrome_bit(\n",
        "        circuit, qreg_data, qreg_measure, creg_syndrome\n",
        "    )\n",
        "\n",
        "    if apply_correction:\n",
        "        circuit = apply_correction_bit(circuit, qreg_data, creg_syndrome)\n",
        "\n",
        "    circuit = apply_final_readout(circuit, qreg_data, creg_data)\n",
        "    return circuit\n",
        "\n",
        "\n",
        "circuit = build_error_correction_sequence(apply_correction=True)\n",
        "circuit.draw(output=\"mpl\", style=\"iqp\", cregbundle=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "609c0c47",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-the-problem-for-quantum-execution\" />\n",
        "\n",
        "## Paso 2. Optimizar el problema para la ejecución cuántica\n",
        "\n",
        "Para reducir el tiempo total de ejecución de los trabajos, Qiskit primitives solo acepta circuitos y observables que se ajusten a las instrucciones y a la conectividad compatibles con el sistema de destino (lo que se conoce como circuitos y observables de arquitectura de conjunto de instrucciones (ISA)).  [Más información sobre la transpilación](/docs/guides/transpile).\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "c8ea2716",
      "metadata": {
        "slideshow": {
          "slide_type": "-"
        }
      },
      "source": [
        "<span id=\"generate-isa-circuits\" />\n",
        "\n",
        "### Generar circuitos ISA\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "67b55eef",
      "metadata": {
        "slideshow": {
          "slide_type": "-"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/repetition-codes/extracted-outputs/67b55eef-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/repetition-codes/extracted-outputs/67b55eef-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_circuit = pm.run(circuit)\n",
        "\n",
        "isa_circuit.draw(\"mpl\", style=\"iqp\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "67acea4f",
      "metadata": {},
      "outputs": [],
      "source": [
        "no_correction_circuit = build_error_correction_sequence(\n",
        "    apply_correction=False\n",
        ")\n",
        "\n",
        "isa_no_correction_circuit = pm.run(no_correction_circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bcd61a1f",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "## Paso 3. Ejecutar utilizando Qiskit primitives\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e68d10d2",
      "metadata": {},
      "source": [
        "Ejecute la versión con corrección aplicada y otra sin corrección.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d53319ba",
      "metadata": {},
      "outputs": [],
      "source": [
        "sampler_no_correction = Sampler(backend)\n",
        "job_no_correction = sampler_no_correction.run(\n",
        "    [isa_no_correction_circuit], shots=1000\n",
        ")\n",
        "result_no_correction = job_no_correction.result()[0]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "df7421d0",
      "metadata": {
        "slideshow": {
          "slide_type": "-"
        }
      },
      "outputs": [],
      "source": [
        "sampler_with_correction = Sampler(backend)\n",
        "\n",
        "job_with_correction = sampler_with_correction.run([isa_circuit], shots=1000)\n",
        "result_with_correction = job_with_correction.result()[0]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "1cba37f5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Data (no correction):\n",
            "{'111': 878, '011': 42, '110': 35, '101': 40, '100': 1, '001': 2, '000': 2}\n",
            "Syndrome (no correction):\n",
            "{'00': 942, '10': 33, '01': 22, '11': 3}\n"
          ]
        }
      ],
      "source": [
        "print(f\"Data (no correction):\\n{result_no_correction.data.data.get_counts()}\")\n",
        "print(\n",
        "    f\"Syndrome (no correction):\\n{result_no_correction.data.syndrome.get_counts()}\"\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "7b7697f2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Data (corrected):\n",
            "{'111': 889, '110': 25, '000': 11, '011': 45, '101': 17, '010': 10, '001': 2, '100': 1}\n",
            "Syndrome (corrected):\n",
            "{'00': 929, '01': 39, '10': 20, '11': 12}\n"
          ]
        }
      ],
      "source": [
        "print(f\"Data (corrected):\\n{result_with_correction.data.data.get_counts()}\")\n",
        "print(\n",
        "    f\"Syndrome (corrected):\\n{result_with_correction.data.syndrome.get_counts()}\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1b652319",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-return-result-in-classical-format\" />\n",
        "\n",
        "## Paso 4. Procesamiento posterior, devolución del resultado en formato clásico\n",
        "\n",
        "Se puede ver que el código de inversión de bits detectó y corrigió muchos errores, lo que dio como resultado menos errores en general.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fa59fb42",
      "metadata": {
        "slideshow": {
          "slide_type": "-"
        }
      },
      "outputs": [],
      "source": [
        "def decode_result(data_counts, syndrome_counts):\n",
        "    shots = sum(data_counts.values())\n",
        "    success_trials = data_counts.get(\"000\", 0) + data_counts.get(\"111\", 0)\n",
        "    failed_trials = shots - success_trials\n",
        "    error_correction_events = shots - syndrome_counts.get(\"00\", 0)\n",
        "    print(\n",
        "        f\"Bit flip errors were detected/corrected on \"\n",
        "        f\"{error_correction_events}/{shots} trials.\"\n",
        "    )\n",
        "    print(\n",
        "        f\"A final parity error was detected on \"\n",
        "        f\"{failed_trials}/{shots} trials.\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "5b1ff3a3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Completed bit code experiment data measurement counts (no correction): {'111': 878, '011': 42, '110': 35, '101': 40, '100': 1, '001': 2, '000': 2}\n",
            "Completed bit code experiment syndrome measurement counts (no correction): {'00': 942, '10': 33, '01': 22, '11': 3}\n",
            "Bit flip errors were detected/corrected on 58/1000 trials.\n",
            "A final parity error was detected on 120/1000 trials.\n"
          ]
        }
      ],
      "source": [
        "# non-corrected marginalized results\n",
        "data_result = result_no_correction.data.data.get_counts()\n",
        "marginalized_syndrome_result = result_no_correction.data.syndrome.get_counts()\n",
        "\n",
        "print(\n",
        "    f\"Completed bit code experiment data measurement counts (no correction): \"\n",
        "    f\"{data_result}\"\n",
        ")\n",
        "print(\n",
        "    f\"Completed bit code experiment syndrome measurement counts (no correction): \"\n",
        "    f\"{marginalized_syndrome_result}\"\n",
        ")\n",
        "decode_result(data_result, marginalized_syndrome_result)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "7f1c2d48",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Completed bit code experiment data measurement counts (corrected): {'111': 889, '110': 25, '000': 11, '011': 45, '101': 17, '010': 10, '001': 2, '100': 1}\n",
            "Completed bit code experiment syndrome measurement counts (corrected): {'00': 929, '01': 39, '10': 20, '11': 12}\n",
            "Bit flip errors were detected/corrected on 71/1000 trials.\n",
            "A final parity error was detected on 100/1000 trials.\n"
          ]
        }
      ],
      "source": [
        "# corrected marginalized results\n",
        "corrected_data_result = result_with_correction.data.data.get_counts()\n",
        "corrected_syndrome_result = result_with_correction.data.syndrome.get_counts()\n",
        "\n",
        "print(\n",
        "    f\"Completed bit code experiment data measurement counts (corrected): \"\n",
        "    f\"{corrected_data_result}\"\n",
        ")\n",
        "print(\n",
        "    f\"Completed bit code experiment syndrome measurement counts (corrected): \"\n",
        "    f\"{corrected_syndrome_result}\"\n",
        ")\n",
        "decode_result(corrected_data_result, corrected_syndrome_result)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b66026c4",
      "metadata": {},
      "source": [
        "<span id=\"tutorial-survey\" />\n",
        "\n",
        "## Encuesta tutorial\n",
        "\n",
        "Responda a esta breve encuesta para darnos su opinión sobre este tutorial. Su opinión nos ayudará a mejorar nuestra oferta de contenidos y la experiencia de los usuarios.\n",
        "\n",
        "[Enlace a la encuesta](https://your.feedback.ibm.com/jfe/form/SV_5onAlfA2Y7ac1FA)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "celltoolbar": "Slideshow",
    "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": 1.5,
    "qpuSeconds": 60
  },
  "nbformat": 4,
  "nbformat_minor": 5
}