{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Limitando a dimensão do subespaço\"\n",
        "description: \"Limitação da dimensão do subespaço para a versão mais recente da diagonalização quântica baseada em amostras (SQD)\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9e40af77-7f0f-4dd6-ab0a-420cf396050e",
      "metadata": {},
      "source": [
        "<span id=\"bounding-the-subspace-dimension\" />\n",
        "\n",
        "# Limitando a dimensão do subespaço\n",
        "\n",
        "{/* cspell:ignore hcore */}\n",
        "\n",
        "Neste passo a passo, mostraremos o efeito da dimensão do subespaço na [técnica de recuperação de configuração autoconsistente](https://arxiv.org/abs/2405.05068).\n",
        "\n",
        "*A priori*, não sabemos qual é a dimensão correta do subespaço para atingir um nível alvo de precisão. No entanto, sabemos que aumentar a dimensão do subespaço aumenta a precisão do método. Portanto, podemos estudar a precisão das previsões em função da dimensão do subespaço.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a6755afb-ca1e-4473-974b-ba89acc8abce",
      "metadata": {},
      "source": [
        "Especifique a molécula e suas propriedades.\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": [
        "Gere algumas sequências de bits aleatórias para simular amostras da 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": [
        "Chame a função SQD com tamanhos de lote crescentes.\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 mostra que o aumento da dimensão do subespaço leva a resultados mais 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
}