{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Comprender las opciones de «capa abierta» frente a «capa cerrada» y su efecto en la construcción de subespacios\"\n",
        "description: \"Comprender las opciones de «capa abierta» frente a «capa cerrada» y su efecto en la construcción de subespacios para la última versión de la diagonalización cuántica basada en muestras (SQD)\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "72420c62-2716-4f64-ad5b-73394b481cc1",
      "metadata": {},
      "source": [
        "<span id=\"understand-open-shell-versus-closed-shell-options-and-the-effect-on-subspace-construction\" />\n",
        "\n",
        "# Comprender las opciones de «capa abierta» frente a «capa cerrada» y su efecto en la construcción de subespacios\n",
        "\n",
        "En esta guía, mostraremos cómo elegir las dimensiones del subespacio en el `qiskit_addon_sqd` paquete para procesar posteriormente muestras cuánticas utilizando [la técnica de recuperación de configuración autoconsistente](https://arxiv.org/abs/2405.05068).\n",
        "\n",
        "Y lo que es más importante, esta guía también destaca algunas diferencias en el comportamiento de la construcción del subespacio cuando se ejecuta en `open_shell = False` los modos o `open_shell = True` :\n",
        "\n",
        "* `open_shell = False` solo funciona cuando el número de electrones en fase de aceleración y de desaceleración es el mismo.\n",
        "\n",
        "* `open_shell = True` Debe utilizarse cuando el número de electrones en fase de aceleración y de desaceleración es diferente. También se puede utilizar cuando el número de electrones en estado de aceleración y de desaceleración es el mismo. Sin embargo, en este último caso, existe una diferencia en el tamaño de los subespacios generados entre `open_shell = False` y `open_shell = True`, tal y como se explica en esta guía.\n",
        "\n",
        "**NOTA:** Algunas de las manipulaciones de la configuración electrónica (cadena de bits) de este paquete tienen como objetivo preservar la simetría de espín total $S^2$. Los solucionadores estándar de la Interacción de Configuración Seleccionada (SCI) no pueden imponer exactamente la conservación de $S^2$. Por consiguiente, lo hacen, aproximadamente, mediante un multiplicador de Lagrange.\n",
        "\n",
        "La elección de las configuraciones electrónicas que se introducen en el solucionador de estados propios también puede tener un gran impacto en la conservación del espín. Por ejemplo, en un sistema (2 electrones, 2 orbitales), se puede muestrear la configuración $|1001\\rangle$ (que presenta una única excitación de espín hacia arriba sobre el estado RHF $|0101\\rangle$ ), la cual es una combinación lineal de los estados de singulete y triplete de capa abierta, respectivamente $(|1001\\rangle ± |0110\\rangle) /\\sqrt{2}$. Si no se incluye la configuración |0110⟩, no es posible construir ninguna de las funciones propias del espín total, lo que da lugar a contaminación o redundancia de espín (la configuración |1001⟩ está incluida en un cálculo de CI, pero tiene coeficiente 0 en el vector CI). Dado que en el ordenador cuántico se genera una única muestra $|1001\\rangle$, así es como el `sqd` paquete gestiona esta situación:\n",
        "\n",
        "* `open_shell = False`:\n",
        "\n",
        "  1. La cadena de bits « $1001$ » se divide en dos partes, que representan las configuraciones de «spin-up» y «spin-down»: « $10$ » (arriba) y « $01$ » (abajo).\n",
        "\n",
        "  2. Se ha elaborado la lista de configuraciones únicas con polarización de espín: $\\mathcal{U} = [01, 10]$.\n",
        "\n",
        "  3. A continuación, consideramos todas las combinaciones posibles de elementos de la función de $\\mathcal{U}$ para formar la base: $\\left \\{ |0101\\rangle, |0110\\rangle , |1001\\rangle , |1010\\rangle \\right \\}$, que contiene los estados de singulete y de triplete.\n",
        "\n",
        "* `open_shell = True`:\n",
        "\n",
        "  1. A diferencia de lo que `open_shell = False` ocurre en ese caso, no combinamos las mitades de la cadena de bits para formar la base.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a6755afb-ca1e-4473-974b-ba89acc8abce",
      "metadata": {},
      "source": [
        "<span id=\"closed-shell\" />\n",
        "\n",
        "### De carcasa cerrada\n",
        "\n",
        "Este ejemplo muestra cómo se manipulan las cadenas de bits en un sistema (de 2 electrones y 4 orbitales).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "677f54ac-b4ed-47e3-b5ba-5366d3a520f9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Specify molecule properties\n",
        "num_orbitals = 4\n",
        "num_elec_a = num_elec_b = 1\n",
        "open_shell = False"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c58e988c-a109-44cd-a975-9df43250c318",
      "metadata": {},
      "source": [
        "Especifica manualmente un diccionario de resultados de medición:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "e9506e0b-ed64-48bb-a97a-ef851b604af1",
      "metadata": {},
      "outputs": [],
      "source": [
        "counts_dict = {\n",
        "    \"00010010\": 1 / 2.0 - 0.01,\n",
        "    \"01001000\": 1 / 2.0 - 0.01,\n",
        "    \"00010001\": 0.02,\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "851bc98e-9c08-4e78-9472-36301abc11d8",
      "metadata": {},
      "source": [
        "Transforma los recuentos `dict` en una matriz de cadenas de bits y en una matriz de probabilidades para su posterior procesamiento:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "7a102a7f-aae6-4583-ab82-ae40fcb5496a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[[False False False  True False False  True False]\n",
            " [False  True False False  True False False False]\n",
            " [False False False  True False False False  True]]\n",
            "[0.49 0.49 0.02]\n"
          ]
        }
      ],
      "source": [
        "from qiskit_addon_sqd.counts import counts_to_arrays\n",
        "\n",
        "# Convert counts into bitstring and probability arrays\n",
        "bitstring_matrix_full, probs_arr_full = counts_to_arrays(counts_dict)\n",
        "print(bitstring_matrix_full)\n",
        "print(probs_arr_full)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "eb704101-0fe8-4d12-b572-b1d844e35a90",
      "metadata": {},
      "source": [
        "Realizar un submuestreo de un único lote de tamaño dos:\n",
        "\n",
        "* `n_batches = 1`: Número de lotes de configuraciones utilizados por las diferentes llamadas al solucionador de estados propios\n",
        "* `samples_per_batch = 2`: Número de configuraciones únicas que se deben incluir en cada lote\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "fe60aee2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[[False False False  True False False  True False]\n",
            " [False  True False False  True False False False]]\n"
          ]
        }
      ],
      "source": [
        "from qiskit_addon_sqd.subsampling import postselect_and_subsample\n",
        "\n",
        "n_batches = 1\n",
        "samples_per_batch = 2\n",
        "\n",
        "# seed for random number generator\n",
        "rand_seed = 48\n",
        "\n",
        "# Generate the batches\n",
        "batches = postselect_and_subsample(\n",
        "    bitstring_matrix_full,\n",
        "    probs_arr_full,\n",
        "    hamming_right=num_elec_a,\n",
        "    hamming_left=num_elec_b,\n",
        "    samples_per_batch=samples_per_batch,\n",
        "    num_batches=n_batches,\n",
        "    rand_seed=rand_seed,\n",
        ")\n",
        "\n",
        "print(batches[0])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "93a6d05a",
      "metadata": {},
      "source": [
        "Obtener la representación decimal de las cadenas de bits de «spin-up» y «spin-down» utilizadas por el solucionador de estados propios.\n",
        "\n",
        "El primer elemento de la tupla corresponde a la representación decimal de las configuraciones de espín hacia arriba, mientras que el segundo elemento de la tupla corresponde a la representación decimal de las configuraciones de espín hacia abajo:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "ef90e039",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "(array([1, 2, 4, 8], dtype=int64), array([1, 2, 4, 8], dtype=int64))\n"
          ]
        }
      ],
      "source": [
        "from qiskit_addon_sqd.fermion import bitstring_matrix_to_ci_strs\n",
        "\n",
        "ci_strs = bitstring_matrix_to_ci_strs(batches[0], open_shell=open_shell)\n",
        "print(ci_strs)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "70d7883c",
      "metadata": {},
      "source": [
        "Cabe señalar que, aunque el número de muestras por lote es dos, y las cadenas de bits muestreadas son: $00010010$ y $01001000$, se generan cuatro configuraciones electrónicas por especie de espín. En este caso, el conjunto de configuraciones únicas con polarización de espín viene dado por:\n",
        "\n",
        "$$\n",
        "\\mathcal{U} = \\{ 0001, 0010, 0100, 1000 \\}\n",
        "$$\n",
        "\n",
        "cuya representación decimal base-10 es\n",
        "\n",
        "$$\n",
        "\\mathcal{U}_{10} = \\{ 1, 2, 4, 8 \\}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "03b32ed5",
      "metadata": {},
      "source": [
        "Base del subespacio:\n",
        "\n",
        "El solucionador de estados propios toma todos los pares posibles de cadenas de bits de espín hacia arriba y espín hacia abajo para construir la base $\\mathcal{B}$ del subespacio:\n",
        "\n",
        "* Elemento 1: $|00010001\\rangle$\n",
        "\n",
        "* Elemento 2: $|00010010\\rangle$\n",
        "\n",
        "* Elemento 3: $|00010100\\rangle$\n",
        "\n",
        "* Elemento 4: $|00011000\\rangle$\n",
        "\n",
        "* Elemento 5: $|00100001\\rangle$\n",
        "\n",
        "* Elemento 6: $|00100010\\rangle$\n",
        "\n",
        "* Elemento 7: $|00100100\\rangle$\n",
        "\n",
        "* Elemento 8: $|00101000\\rangle$\n",
        "\n",
        "* Elemento 9: $|01000001\\rangle$\n",
        "\n",
        "* Elemento 10: $|01000010\\rangle$\n",
        "\n",
        "* Elemento 11: $|01000100\\rangle$\n",
        "\n",
        "* Elemento 12: $|01001000\\rangle$\n",
        "\n",
        "* Elemento 13: $|10000001\\rangle$\n",
        "\n",
        "* Elemento 14: $|10000010\\rangle$\n",
        "\n",
        "* Elemento 15: $|10000100\\rangle$\n",
        "\n",
        "* Elemento 16: $|10001000\\rangle$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "11c924ee",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Basis elements of the subspace:\n",
            "|00010001>\n",
            "|00010010>\n",
            "|00010100>\n",
            "|00011000>\n",
            "|00100001>\n",
            "|00100010>\n",
            "|00100100>\n",
            "|00101000>\n",
            "|01000001>\n",
            "|01000010>\n",
            "|01000100>\n",
            "|01001000>\n",
            "|10000001>\n",
            "|10000010>\n",
            "|10000100>\n",
            "|10001000>\n"
          ]
        }
      ],
      "source": [
        "ci_strs_up, ci_strs_dn = ci_strs\n",
        "\n",
        "print(\"Basis elements of the subspace:\")\n",
        "\n",
        "for ci_str_up in ci_strs_up:\n",
        "    for ci_str_dn in ci_strs_dn:\n",
        "        format_name = \"{0:0\" + str(num_orbitals) + \"b}\"\n",
        "        print(\n",
        "            \"|\"\n",
        "            + format_name.format(ci_str_up)\n",
        "            + format_name.format(ci_str_dn)\n",
        "            + \">\"\n",
        "        )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "aa43a4fc",
      "metadata": {},
      "source": [
        "**La dimensión del subespacio tiene como límite superior** : $2 \\cdot$ (`samples_per_batch`) $^2$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9412e52b",
      "metadata": {},
      "source": [
        "<span id=\"open-shell\" />\n",
        "\n",
        "### De carcasa abierta\n",
        "\n",
        "Este ejemplo muestra cómo se manipulan las cadenas de bits en un sistema (de 2 electrones y 4 orbitales).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "9b515b8a",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Specify molecule properties\n",
        "num_orbitals = 4\n",
        "num_elec_a = num_elec_b = 1\n",
        "open_shell = True"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9ef78560",
      "metadata": {},
      "source": [
        "Especifica manualmente un diccionario de resultados de medición:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "06b2185a",
      "metadata": {},
      "outputs": [],
      "source": [
        "counts_dict = {\n",
        "    \"00010010\": 1 / 2.0 - 0.01,\n",
        "    \"01001000\": 1 / 2.0 - 0.01,\n",
        "    \"00010001\": 0.02,\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "08b32957",
      "metadata": {},
      "source": [
        "Transforma los recuentos `dict` en una matriz de cadenas de bits y en una matriz de probabilidades para su posterior procesamiento:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "90561893",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[[False False False  True False False  True False]\n",
            " [False  True False False  True False False False]\n",
            " [False False False  True False False False  True]]\n",
            "[0.49 0.49 0.02]\n"
          ]
        }
      ],
      "source": [
        "# Convert counts into bitstring and probability arrays\n",
        "bitstring_matrix_full, probs_arr_full = counts_to_arrays(counts_dict)\n",
        "print(bitstring_matrix_full)\n",
        "print(probs_arr_full)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "416bfb6c",
      "metadata": {},
      "source": [
        "Realizar un submuestreo de un único lote de tamaño dos:\n",
        "\n",
        "* `n_batches = 1`: Número de lotes de configuraciones utilizados por las diferentes llamadas al solucionador de estados propios\n",
        "* `samples_per_batch = 2`: Número de configuraciones únicas que se deben incluir en cada lote\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "cf4fe11d",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[[False False False  True False False  True False]\n",
            " [False  True False False  True False False False]]\n"
          ]
        }
      ],
      "source": [
        "n_batches = 1\n",
        "samples_per_batch = 2\n",
        "\n",
        "# seed for random number generator\n",
        "rand_seed = 48\n",
        "\n",
        "# Generate the batches\n",
        "batches = postselect_and_subsample(\n",
        "    bitstring_matrix_full,\n",
        "    probs_arr_full,\n",
        "    hamming_right=num_elec_a,\n",
        "    hamming_left=num_elec_b,\n",
        "    samples_per_batch=samples_per_batch,\n",
        "    num_batches=n_batches,\n",
        "    rand_seed=rand_seed,\n",
        ")\n",
        "\n",
        "print(batches[0])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "54d699ca",
      "metadata": {},
      "source": [
        "Obtener la representación decimal de las cadenas de bits de «spin-up» y «spin-down» utilizadas por el solucionador de estados propios.\n",
        "\n",
        "El primer elemento de la tupla corresponde a la representación decimal de las configuraciones de espín hacia arriba, mientras que el segundo elemento de la tupla corresponde a la representación decimal de las configuraciones de espín hacia abajo:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "b40b049b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "(array([2, 8], dtype=int64), array([1, 4], dtype=int64))\n"
          ]
        }
      ],
      "source": [
        "ci_strs = bitstring_matrix_to_ci_strs(batches[0], open_shell=open_shell)\n",
        "print(ci_strs)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "28921e56",
      "metadata": {},
      "source": [
        "Si especificamos que `open_shell = True`, no incluimos todas las semicadenas de bits únicas como configuraciones de «spin-up» y «spin-down», lo que da lugar a una base más reducida que cuando se especifica `open_shell = False`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e1959b72",
      "metadata": {},
      "source": [
        "Base del subespacio:\n",
        "\n",
        "El solucionador de estados propios toma todos los pares posibles de cadenas de bits de espín hacia arriba y espín hacia abajo para construir la base $\\mathcal{B}$ del subespacio:\n",
        "\n",
        "* Elemento 1: $|00010010\\rangle$\n",
        "\n",
        "* Elemento 2: $|00011000\\rangle$\n",
        "\n",
        "* Elemento 3: $|01000010\\rangle$\n",
        "\n",
        "* Elemento 4: $|01001000\\rangle$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "a550aba2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Basis elements of the subspace:\n",
            "|00100001>\n",
            "|00100100>\n",
            "|10000001>\n",
            "|10000100>\n"
          ]
        }
      ],
      "source": [
        "ci_strs_up, ci_strs_dn = ci_strs\n",
        "\n",
        "print(\"Basis elements of the subspace:\")\n",
        "\n",
        "for ci_str_up in ci_strs_up:\n",
        "    for ci_str_dn in ci_strs_dn:\n",
        "        format_name = \"{0:0\" + str(num_orbitals) + \"b}\"\n",
        "        print(\n",
        "            \"|\"\n",
        "            + format_name.format(ci_str_up)\n",
        "            + format_name.format(ci_str_dn)\n",
        "            + \">\"\n",
        "        )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7317bc49",
      "metadata": {},
      "source": [
        "**La dimensión del subespacio tiene como límite superior** : (`samples_per_batch`) $^2$.\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": 5
}