{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "1379da5d-023f-42e7-8a3f-ea8c1e3a1d46",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Diagonalización cuántica de Krylov basada en muestras\"\n",
        "description: \"Los temas de las lecciones anteriores se combinan para aprovechar las garantías de convergencia de QKD y la velocidad de SQD en SKQD.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore arxiv Neel probs eigenvals Hatano */}\n",
        "\n",
        "<span id=\"sample-based-krylov-quantum-diagonalization-skqd\" />\n",
        "\n",
        "# Diagonalización cuántica de Krylov basada en muestras (SKQD)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "97cfd899-4196-4d24-bf16-60bdd3899600",
      "metadata": {},
      "source": [
        "Esta lección sobre Diagonalización cuántica de Krylov basada en muestras (SKQD) combina métodos explicados en métodos anteriores. Consiste en un único ejemplo que aprovecha el marco de patrones Qiskit:\n",
        "\n",
        "* Paso 1: Asignar el problema a circuitos y operadores cuánticos\n",
        "* Paso 2: Optimización para el hardware de destino\n",
        "* Paso 3: Ejecutar utilizando primitivas de « IBM Quantum »\n",
        "* Paso 4: Tratamiento posterior\n",
        "\n",
        "Un paso importante en el método de diagonalización cuántica basado en muestras es generar vectores de calidad para el subespacio. En la lección anterior, utilizamos el ansatz LUCJ para generar vectores subespaciales para un Hamiltoniano de química. En esta lección, utilizaremos los estados cuánticos de Krylov [\\[1\\]](#references) tal y como se discutió en la lección 2. En primer lugar, repasaremos cómo crear el espacio de Krylov en un ordenador cuántico utilizando operaciones de evolución temporal. A continuación, tomaremos una muestra. Proyectaremos el Hamiltoniano del sistema en el subespacio muestreado y lo diagonalizaremos para estimar la energía del estado base. El algoritmo converge de forma demostrable y eficiente al estado fundamental, bajo los supuestos descritos en la lección 2.\n",
        "\n",
        "<span id=\"0-the-krylov-space\" />\n",
        "\n",
        "## 0. El espacio de Krylov\n",
        "\n",
        "Recordemos que un espacio de Krylov $\\mathcal{K}^r$ de orden $r$ es el espacio abarcado por los vectores obtenidos multiplicando las potencias superiores de una matriz $A$, hasta $r-1$, por un vector de referencia $\\vert v \\rangle$.\n",
        "\n",
        "$$\n",
        "\\mathcal{K}^r = \\left\\{ \\vert v \\rangle, A \\vert v \\rangle, A^2 \\vert v \\rangle, ..., A^{r-1} \\vert v \\rangle \\right\\}\n",
        "$$\n",
        "\n",
        "Si la matriz $A$ es el hamiltoniano $H$, el espacio correspondiente se denomina *espacio de Krylov de potencia* $\\mathcal{K}_P$. Si $A$ es el operador de evolución temporal generado por el hamiltoniano $U=e^{-iH(dt)}$, el espacio se denomina espacio de Krylov unitario $\\mathcal{K}_U$. El subespacio de Krylov de potencia no puede generarse directamente en una computadora cuántica, ya que $H$ no es un operador unitario. En su lugar, podemos utilizar el operador de evolución temporal $U = e^{-iH(dt)}$, que puede demostrarse que ofrece [garantías de convergencia](https://arxiv.org/abs/2110.07492) similares a las del espacio de Krylov de potencia. Las potencias de $U$ se convierten entonces en diferentes pasos temporales $U^k = e^{-iH(k dt)}$ donde $k = 0, 1, 2, ..., (r-1)$.\n",
        "\n",
        "$$\n",
        "\\mathcal{K}_U^r = \\left\\{ \\vert \\psi \\rangle, U \\vert \\psi \\rangle, U^2 \\vert \\psi \\rangle, ..., U^{r-1} \\vert \\psi \\rangle \\right\\}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "864a0ce7-d094-48ea-9cf0-2a7e38791815",
      "metadata": {},
      "source": [
        "<span id=\"1-map-problem-to-quantum-circuits-and-operators\" />\n",
        "\n",
        "## 1. Asignar el problema a circuitos y operadores cuánticos\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5888e3e8-51a1-426a-9023-c137aa9c6c83",
      "metadata": {},
      "source": [
        "En esta lección, consideramos el Hamiltoniano para la cadena antiferromagnética XX-Z spin-1/2 con $L = 22$ sitios con la condición de frontera periódica:\n",
        "\n",
        "$$\n",
        "    H = \\sum_{i, j}^{N} J_{xy} (X_{i} X_{j} + Y_{i} Y_{j}) + Z_{i} Z_{j}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "f0d3e153-17da-4457-b1d2-2a35d31aea3a",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import CouplingMap\n",
        "from qiskit_addon_utils.problem_generators import generate_xyz_hamiltonian\n",
        "\n",
        "num_spins = 22\n",
        "coupling_map = CouplingMap.from_ring(num_spins)\n",
        "H_op = generate_xyz_hamiltonian(coupling_map, coupling_constants=(0.3, 0.3, 1.0))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b0660e0d-5521-4095-a810-949729421b57",
      "metadata": {},
      "source": [
        "Para construir el espacio de Krylov, necesitamos tres ingredientes principales:\n",
        "\n",
        "1. Una elección de la dimensión de Krylov ( $r$ ) y del paso temporal ( $dt$ ).\n",
        "2. Un estado inicial (de referencia) (vector $\\vert v \\rangle$ anterior) con solapamiento polinómico con el estado objetivo (base), donde el estado objetivo es disperso. Este requisito de solapamiento polinómico es el mismo que en el algoritmo de estimación de fase cuántica.\n",
        "3. Operadores de evolución temporal $U^{k}=e^{-iH(k * dt)}$ ( $k = 0, 1, 2, ..., r-1$ ).\n",
        "\n",
        "Para un valor elegido de $r$ (y, $dt$ ), crearemos $r$ circuitos cuánticos separados y tomaremos muestras de ellos. Cada circuito cuántico se crea uniendo la representación del circuito cuántico del estado de referencia y el operador de evolución temporal para un valor $k$.\n",
        "\n",
        "Una dimensión de Krylov mayor mejora la convergencia de la energía estimada. En esta lección fijamos la dimensión en $5$ para ilustrar la tendencia a la convergencia.\n",
        "\n",
        "La referencia [\\[2\\]](#references) demostró que un paso de tiempo suficientemente pequeño para KQD es $\\pi / \\vert \\vert H \\vert \\vert$, y que es preferible subestimar este valor que sobreestimarlo. Por otro lado, elegir $dt$ demasiado pequeño conduce a un peor acondicionamiento del subespacio de Krylov, ya que los vectores base de Krylov difieren menos de un paso temporal a otro. Además, aunque se ha demostrado que esta elección de $dt$ es adecuada para la convergencia de SKQD, en este contexto basado en el muestreo la elección óptima de $dt$ en la práctica es un tema de estudio en curso. En esta lección, configuramos $dt = 0.15$.\n",
        "\n",
        "Además de la dimensión de Krylov y el paso temporal, necesitamos establecer el número de pasos de Trotter para la evolución temporal. Utilizar muy pocos pasos conduce a mayores errores de trotterización, mientras que demasiados pasos conducen a circuitos más profundos. En esta lección, fijamos el número de pasos de Trotter en $6$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "52eb15e3-e06c-4820-bad1-80fb7c05feee",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Set parameters for quantum Krylov algorithm\n",
        "krylov_dim = 5  # size of krylov subspace\n",
        "dt = 0.15\n",
        "num_trotter_steps = 6"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a716ea3e-b3d6-42de-8ed5-331e6416e586",
      "metadata": {},
      "source": [
        "A continuación, tenemos que elegir un estado de referencia $\\vert \\psi \\rangle$ que tenga cierto solapamiento con el estado de tierra. Para este Hamiltoniano, utilizamos el estado *Neel* con alternancia de 1s y 0s $\\vert ...101...010...101 \\rangle$ como nuestro estado de referencia.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "53347df7-b43c-4859-a9ea-a3dea2a44184",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Prep `Neel` state as the reference state for evolution\n",
        "from qiskit import QuantumCircuit\n",
        "\n",
        "qc_state_prep = QuantumCircuit(num_spins)\n",
        "for i in range(num_spins):\n",
        "    if i % 2 == 0:\n",
        "        qc_state_prep.x(i)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6952aaf2-c598-4ce9-8dc5-e63f0725de10",
      "metadata": {},
      "source": [
        "Por último, necesitamos asignar el operador de evolución temporal a un circuito cuántico. Esto se hizo en la lección 2, pero aquí vamos a aprovechar los métodos en Qiskit, específicamente un método llamado *síntesis*. Existen diferentes métodos para sintetizar operadores matemáticos en circuitos cuánticos con puertas cuánticas. Muchas de estas técnicas están disponibles en [el módulo de síntesis de Qiskit](/docs/api/qiskit/synthesis). Utilizaremos el [`LieTrotter`](/docs/api/qiskit/qiskit.synthesis.LieTrotter) enfoque de síntesis [\\[3\\]](#references) [\\[4\\]](#references).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "c82afe58-a90a-49a9-9dfe-c24b2b5d0a8c",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit import QuantumRegister\n",
        "from qiskit.circuit.library import PauliEvolutionGate\n",
        "from qiskit.synthesis import LieTrotter\n",
        "\n",
        "evol_gate = PauliEvolutionGate(\n",
        "    H_op, time=(dt / num_trotter_steps), synthesis=LieTrotter(reps=num_trotter_steps)\n",
        ")  # `U` operator\n",
        "\n",
        "qr = QuantumRegister(num_spins)\n",
        "qc_evol = QuantumCircuit(qr)\n",
        "qc_evol.append(evol_gate, qargs=qr)\n",
        "\n",
        "circuits = []\n",
        "for rep in range(krylov_dim):\n",
        "    circ = qc_state_prep.copy()\n",
        "\n",
        "    # Repeating the `U` operator to implement U^0, U^1, U^2, and so on, for power Krylov space\n",
        "    for _ in range(rep):\n",
        "        circ.compose(other=qc_evol, inplace=True)\n",
        "\n",
        "    circ.measure_all()\n",
        "    circuits.append(circ)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "7ffc3eaa-9563-4c89-9d7b-808a3a37b275",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/quantum-diagonalization-algorithms/qda-5-skqd/extracted-outputs/7ffc3eaa-9563-4c89-9d7b-808a3a37b275-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "circuits[1].decompose().draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "bdbc0881-06b0-49f2-8919-a376aa7f08e3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/quantum-diagonalization-algorithms/qda-5-skqd/extracted-outputs/bdbc0881-06b0-49f2-8919-a376aa7f08e3-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "circuits[2].decompose().draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9b43f693-b6d0-43cb-b982-3f8a3b6e185d",
      "metadata": {},
      "source": [
        "<span id=\"2-optimize-for-target-hardware\" />\n",
        "\n",
        "## 2. Optimizar para el hardware de destino\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6ed5a22f-4bdc-4a8d-ad39-5307308d0cc4",
      "metadata": {},
      "source": [
        "Ahora que hemos creado los circuitos, podemos optimizarlos para un hardware de destino. Elegimos una QPU a escala de servicio público.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "8944305a-0f29-4f97-a04f-43249cdc02ea",
      "metadata": {},
      "outputs": [],
      "source": [
        "import warnings\n",
        "\n",
        "from qiskit import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "warnings.filterwarnings(\"ignore\")\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "# Use the least-busy backend or specify a quantum computer using the syntax commented out below.\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "# backend = service.backend(\"ibm_brisbane\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3ed422ad-04f5-4f1f-a142-f08a0ac0a34b",
      "metadata": {},
      "source": [
        "Ahora, transpilamos los circuitos al backend de destino utilizando un gestor de pases preestablecido.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "8a72b655-ccee-4927-8bf2-b99d0b92723a",
      "metadata": {},
      "outputs": [],
      "source": [
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "isa_circuits = pm.run(circuits=circuits)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6405ab01-5cec-4a02-8846-f9ba626d9cdc",
      "metadata": {},
      "source": [
        "<span id=\"3-execute-on-target-hardware\" />\n",
        "\n",
        "## 3. Ejecutar en el hardware de destino\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6aa67e8c-30db-4e11-9bf2-150c157ec49c",
      "metadata": {},
      "source": [
        "Una vez optimizados los circuitos para su ejecución en hardware, estamos listos para ejecutarlos en el hardware de destino y recoger muestras para la estimación de la energía del estado fundamental.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "0613c95b-e696-4ddb-8f51-dc1714d21a0e",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
        "\n",
        "sampler = Sampler(mode=backend)\n",
        "job = sampler.run(isa_circuits, shots=100_000)  # Takes approximately 2m 58s of QPU time"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "1c60e828-9359-46c6-84ef-88aecdb85b81",
      "metadata": {},
      "outputs": [],
      "source": [
        "counts_all = [job.result()[k].data.meas.get_counts() for k in range(krylov_dim)]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fa2fcfe0-66ab-4230-9262-9a46ecda034b",
      "metadata": {},
      "source": [
        "<span id=\"4-post-process-results\" />\n",
        "\n",
        "## 4. Resultados posteriores al procesamiento\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "75321a43-0740-4d13-bdc4-350b44727b62",
      "metadata": {},
      "source": [
        "A continuación, agregamos los recuentos para dimensiones de Krylov crecientes de forma acumulativa. Utilizando los recuentos acumulativos, abarcaremos subespacios de dimensión de Krylov creciente y analizaremos el comportamiento de convergencia.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "9954125c-5ad8-40e8-affa-4a644354c51f",
      "metadata": {},
      "outputs": [],
      "source": [
        "from collections import Counter\n",
        "\n",
        "counts_cumulative = []\n",
        "for i in range(krylov_dim):\n",
        "    counter = Counter()\n",
        "    for d in counts_all[: i + 1]:\n",
        "        counter.update(d)\n",
        "\n",
        "    counts = dict(counter)\n",
        "    counts_cumulative.append(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "14fcdfc2-b37e-4a9c-9794-7c1fa9a6ab1b",
      "metadata": {},
      "source": [
        "Para proyectar y diagonalizar el Hamiltoniano, utilizamos las capacidades de [`qiskit-addon-sqd`](https://qiskit.github.io/qiskit-addon-sqd/). El complemento ofrece funcionalidades para proyectar hamiltonianos basados en cadenas de Pauli en un subespacio y resuelve los valores propios utilizando `SciPy`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "5ace841d-59c6-4ea1-9ceb-6f6436546093",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_addon_sqd.counts import counts_to_arrays\n",
        "from qiskit_addon_sqd.qubit import solve_qubit"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "104cc0fd-4fa0-469b-bfb8-4089cea5145f",
      "metadata": {},
      "source": [
        "En principio, podemos filtrar las cadenas de bits con un patrón incorrecto antes de abarcar el subespacio. Por ejemplo, el estado base para el Hamiltoniano antiferromagnético de esta lección suele tener el mismo número de espines \"arriba\" y \"abajo\", es decir, el número de \"1 \"s en la cadena de bits debe ser exactamente la mitad del número total de bits (espines) en el sistema. La siguiente función filtra de los recuentos las cadenas de bits con un número incorrecto de \"1\".\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 37,
      "id": "81d728a1-6ab4-4664-a7ca-2017dae10e1a",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Filters out bitstrings that do not have specified number (`num_ones`) of `1` bits.\n",
        "def postselect_counts(counts, num_ones):\n",
        "    filtered_counts = {}\n",
        "    for bitstring, freq in counts.items():\n",
        "        if bitstring.count(\"1\") == num_ones:\n",
        "            filtered_counts[bitstring] = freq\n",
        "\n",
        "    return filtered_counts"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d77772f5-fe1c-4a6c-abcb-c2c3c7d7293a",
      "metadata": {},
      "source": [
        "Utilizando cadenas de bits con el número correcto de electrones arriba/abajo, abarcamos subespacios y calculamos valores propios para una dimensión de Krylov creciente. Dependiendo del tamaño del problema y de los recursos clásicos disponibles, puede que tengamos que adoptar el submuestreo (similar a la [lección sobre SQD](/learning/courses/quantum-diagonalization-algorithms/sqd-implementation) ) para mantener la dimensión del subespacio bajo control. Además, podemos aplicar la noción de recuperación de la configuración de forma similar a la Lección 4. Podemos calcular la ocupación de electrones por sitio a partir de los estados propios reconstruidos y utilizar la información para corregir cadenas de bits con un número incorrecto de electrones arriba/abajo. Dejamos esto como ejercicio para los lectores interesados.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 38,
      "id": "f0e0f56f-ec56-40b6-b8be-059be35d2ce5",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "\n",
        "num_batches = 10\n",
        "rand_seed = 0\n",
        "scipy_kwargs = {\"k\": 2, \"which\": \"SA\"}\n",
        "\n",
        "ground_state_energies = []\n",
        "for idx, counts in enumerate(counts_cumulative):\n",
        "    counts = postselect_counts(counts, num_ones=num_spins // 2)\n",
        "    bitstring_matrix, probs = counts_to_arrays(counts=counts)\n",
        "\n",
        "    eigenvals, eigenstates = solve_qubit(\n",
        "        bitstring_matrix, H_op, verbose=False, **scipy_kwargs\n",
        "    )\n",
        "    gs_en = np.min(eigenvals)\n",
        "    ground_state_energies.append(gs_en)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "67b2a04b-4e70-45dc-bd21-2c4340c18377",
      "metadata": {},
      "source": [
        "A continuación, trazamos la energía calculada en función de la dimensión de Krylov y la comparamos con la energía exacta. La energía exacta se calcula por separado utilizando un método clásico de fuerza bruta. Podemos ver que la energía estimada del estado base converge con el aumento de la dimensión del espacio de Krylov. Aunque la dimensión de Krylov de $5$ es limitante, los resultados siguen mostrando una convergencia impresionante, que se espera mejore con una dimensión de Krylov mayor [\\[1\\]](#references).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 39,
      "id": "debca96a-e0e3-4342-a755-8204dba50d74",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/quantum-diagonalization-algorithms/qda-5-skqd/extracted-outputs/debca96a-e0e3-4342-a755-8204dba50d74-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "exact_gs_en = -23.934184\n",
        "plt.plot(\n",
        "    range(1, krylov_dim + 1),\n",
        "    ground_state_energies,\n",
        "    color=\"blue\",\n",
        "    linestyle=\"-.\",\n",
        "    label=\"estimate\",\n",
        ")\n",
        "plt.plot(\n",
        "    range(1, krylov_dim + 1),\n",
        "    [exact_gs_en] * krylov_dim,\n",
        "    color=\"red\",\n",
        "    linestyle=\"-\",\n",
        "    label=\"exact\",\n",
        ")\n",
        "plt.xticks(range(1, krylov_dim + 1), range(1, krylov_dim + 1))\n",
        "plt.legend()\n",
        "plt.xlabel(\"Krylov space dimension\")\n",
        "plt.ylabel(\"Energy\")\n",
        "plt.ylim([-24, -22.50])\n",
        "plt.title(\n",
        "    \"Estimating Ground state energy with Sample-based Krylov Quantum Diagonalization\"\n",
        ")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5865567b-cc32-48dd-b7f9-32ce64d7dd7c",
      "metadata": {},
      "source": [
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Comprueba tu comprensión\n",
        "\n",
        "Lee las preguntas siguientes, piensa tus respuestas y haz clic en los triángulos para descubrir las soluciones.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"¿Qué se podría hacer para mejorar la convergencia en el gráfico anterior?\">\n",
        "    **Respuesta:**\n",
        "\n",
        "    Aumentar la dimensión de Krylov. En general, también se podría aumentar el número de disparos, pero éste ya es bastante elevado en el cálculo anterior.\n",
        "  </AccordionItem>\n",
        "\n",
        "  <AccordionItem title=\"¿Cuáles son las principales ventajas de SKQD sobre (a) SQD y (b) KQD?\">\n",
        "    **Respuesta:**\n",
        "\n",
        "    Puede haber otras respuestas válidas, pero las respuestas completas deben incluir lo siguiente:\n",
        "\n",
        "    (a) SKQD ofrece garantías de convergencia que SQD no ofrece. En SQD, o bien tienes que hacer una suposición muy buena para tu ansatz que tenga un solapamiento excelente con el soporte del estado básico en la base computacional, o bien tienes que introducir un componente variacional en el cálculo para muestrear una familia de ansatz.\n",
        "\n",
        "    (b) SKQD requiere mucho menos tiempo de QPU, porque evita el costoso cálculo de los elementos de la matriz mediante la prueba Hadamard.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a4cf119d-65cf-456c-be0d-731bb7a6799a",
      "metadata": {},
      "source": [
        "<span id=\"5-summary\" />\n",
        "\n",
        "## 5. Resumen\n",
        "\n",
        "* La estimación de la energía del estado básico mediante el muestreo de estados base de Krylov es muy adecuada para los modelos de celosía, incluidos los sistemas de espín, los problemas de materia condensada y las teorías gauge de celosía. Este enfoque se escala mucho mejor que VQE, porque no requiere la optimización sobre muchos parámetros en un ansatz variacional como en VQE, o en SQD basado en ansatz heurístico (por ejemplo, el problema de química de la lección anterior).\n",
        "  * Para mantener baja la profundidad de los circuitos, conviene abordar los problemas de entramado que son susceptibles de hardware tolerante a fallos previos.\n",
        "* SKQD no incurre en un problema de medición cuántica como en VQE. No hay grupos de operadores de Pauli conmutativos que estimar.\n",
        "* SKQD es resistente a las muestras ruidosas, ya que se puede utilizar una rutina de poselección específica para cada problema (por ejemplo, filtrar las cadenas de bits que no se ajustan a los patrones propios del problema) o asumir la sobrecarga que supone la diagonalización clásica (es decir, diagonalizar en un subespacio más amplio) para eliminar de forma eficaz el efecto del ruido.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c52bada7-1912-41f2-a770-3145a947de63",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## Referencias\n",
        "\n",
        "\\[1] Jeffery Yu et al., \"Algoritmo cuántico-céntrico para la diagonalización de Krylov basada en muestras\" (2025). [arxiv:quant-ph/2501.09702](https://arxiv.org/abs/2501.09702).\n",
        "\n",
        "\\[2] Ethan N. Epperly, Lin Lin y Yuji Nakatsukasa. \"Una teoría de diagonalización de subespacios cuánticos\". SIAM Journal on Matrix Analysis and Applications 43, 1263-1290 (2022).\n",
        "\n",
        "\\[2] N. Hatano y M. Suzuki, \"Finding Exponential Product Formulas of Higher Orders\" (2005). [arXiv:math-ph/0506007](https://arxiv.org/abs/math-ph/0506007).\n",
        "\n",
        "\\[4] D. Berry, G. Ahokas, R. Cleve y B. Sanders, \"Efficient quantum algorithms for simulating sparse Hamiltonians\" (2006). [arXiv:quant-ph/0508139](https://arxiv.org/abs/quant-ph/0508139).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}