{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Limitación de la dimensión del subespacio\"\n",
        "description: \"Limitación de la dimensión del subespacio para la última versión de la diagonalización cuántica basada en muestras (SQD)\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9e40af77-7f0f-4dd6-ab0a-420cf396050e",
      "metadata": {},
      "source": [
        "<span id=\"bounding-the-subspace-dimension\" />\n",
        "\n",
        "# Limitación de la dimensión del subespacio\n",
        "\n",
        "{/* cspell:ignore hcore */}\n",
        "\n",
        "En este tutorial, mostraremos el efecto de la dimensión del subespacio en [la técnica de recuperación de la configuración autoconsistente](https://arxiv.org/abs/2405.05068).\n",
        "\n",
        "*A priori*, no sabemos cuál es la dimensión correcta del subespacio para alcanzar el nivel de precisión deseado. Sin embargo, sí sabemos que al aumentar la dimensión del subespacio aumenta la precisión del método. Por lo tanto, podemos estudiar la precisión de las predicciones en función de la dimensión del subespacio.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a6755afb-ca1e-4473-974b-ba89acc8abce",
      "metadata": {},
      "source": [
        "Indica la molécula y sus propiedades.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "677f54ac-b4ed-47e3-b5ba-5366d3a520f9",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "converged SCF energy = -108.835236570775\n",
            "CASCI E = -109.046671778080  E(CI) = -32.8155692383188  S^2 = 0.0000000\n"
          ]
        }
      ],
      "source": [
        "import warnings\n",
        "\n",
        "import pyscf\n",
        "import pyscf.cc\n",
        "import pyscf.mcscf\n",
        "\n",
        "warnings.filterwarnings(\"ignore\")\n",
        "\n",
        "# Specify molecule properties\n",
        "open_shell = False\n",
        "spin_sq = 0\n",
        "\n",
        "# Build N2 molecule\n",
        "mol = pyscf.gto.Mole()\n",
        "mol.build(\n",
        "    atom=[[\"N\", (0, 0, 0)], [\"N\", (1.0, 0, 0)]],\n",
        "    basis=\"6-31g\",\n",
        "    symmetry=\"Dooh\",\n",
        ")\n",
        "\n",
        "# Define active space\n",
        "n_frozen = 2\n",
        "active_space = range(n_frozen, mol.nao_nr())\n",
        "\n",
        "# Get molecular integrals\n",
        "scf = pyscf.scf.RHF(mol).run()\n",
        "num_orbitals = len(active_space)\n",
        "n_electrons = int(sum(scf.mo_occ[active_space]))\n",
        "num_elec_a = (n_electrons + mol.spin) // 2\n",
        "num_elec_b = (n_electrons - mol.spin) // 2\n",
        "cas = pyscf.mcscf.CASCI(scf, num_orbitals, (num_elec_a, num_elec_b))\n",
        "mo = cas.sort_mo(active_space, base=0)\n",
        "hcore, nuclear_repulsion_energy = cas.get_h1cas(mo)\n",
        "eri = pyscf.ao2mo.restore(1, cas.get_h2cas(mo), num_orbitals)\n",
        "\n",
        "# Compute exact energy\n",
        "exact_energy = cas.run().e_tot"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c58e988c-a109-44cd-a975-9df43250c318",
      "metadata": {},
      "source": [
        "Genera algunas cadenas de bits aleatorias para simular muestras de la QPU.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "e9506e0b-ed64-48bb-a97a-ef851b604af1",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from qiskit_addon_sqd.counts import generate_bit_array_uniform\n",
        "\n",
        "# Create a seed to control randomness throughout this workflow\n",
        "rng = np.random.default_rng(24)\n",
        "\n",
        "# Generate random samples\n",
        "bit_array = generate_bit_array_uniform(\n",
        "    10_000, num_orbitals * 2, rand_seed=rng\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "82b062a3-d4ca-41e2-9b00-4a394f83cbdd",
      "metadata": {},
      "source": [
        "Llama a SQD a medida que aumenten los tamaños de los lotes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "e0847f28",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_addon_sqd.fermion import diagonalize_fermionic_hamiltonian\n",
        "\n",
        "list_samples_per_batch = [50, 200, 400, 600]\n",
        "\n",
        "# SQD options\n",
        "max_iterations = 5\n",
        "\n",
        "# Eigenstate solver options\n",
        "num_batches = 10\n",
        "max_davidson_cycles = 200\n",
        "\n",
        "energies = []\n",
        "subspace_dimensions = []\n",
        "\n",
        "for samples_per_batch in list_samples_per_batch:\n",
        "    result = diagonalize_fermionic_hamiltonian(\n",
        "        hcore,\n",
        "        eri,\n",
        "        bit_array,\n",
        "        samples_per_batch=samples_per_batch,\n",
        "        norb=num_orbitals,\n",
        "        nelec=(num_elec_a, num_elec_b),\n",
        "        num_batches=num_batches,\n",
        "        max_iterations=max_iterations,\n",
        "        symmetrize_spin=True,\n",
        "        seed=rng,\n",
        "    )\n",
        "    energies.append(result.energy)\n",
        "    subspace_dimensions.append(np.prod(result.sci_state.amplitudes.shape))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9d78906b-4759-4506-9c69-85d4e67766b3",
      "metadata": {},
      "source": [
        "Este gráfico muestra que al aumentar la dimensión del subespacio se obtienen resultados más precisos.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "caffd888-e89c-4aa9-8bae-4d1bb723b35e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-sqd/guides/choose-subspace-dimension/extracted-outputs/caffd888-e89c-4aa9-8bae-4d1bb723b35e-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "# Data for energies plot\n",
        "x1 = subspace_dimensions\n",
        "y1 = np.array(energies) + nuclear_repulsion_energy\n",
        "\n",
        "fig, axs = plt.subplots(1, 1, figsize=(12, 6))\n",
        "\n",
        "# Plot energies\n",
        "axs.plot(x1, y1, marker=\".\", markersize=20, label=\"Estimated\")\n",
        "axs.set_xticks(x1)\n",
        "axs.set_xticklabels(x1)\n",
        "axs.axhline(y=exact_energy, color=\"red\", linestyle=\"--\", label=\"Exact\")\n",
        "axs.set_title(\"Approximated Ground State Energy vs subspace dimension\")\n",
        "axs.set_xlabel(\"Subspace dimension\")\n",
        "axs.set_ylabel(\"Energy (Ha)\")\n",
        "axs.legend()\n",
        "\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()"
      ]
    },
    {
      "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
}