{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Determinazione della dimensione del sottospazio\"\n",
        "description: \"Limiti della dimensione del sottospazio per l'ultima versione della diagonalizzazione quantistica basata su campioni (SQD)\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9e40af77-7f0f-4dd6-ab0a-420cf396050e",
      "metadata": {},
      "source": [
        "<span id=\"bounding-the-subspace-dimension\" />\n",
        "\n",
        "# Determinazione della dimensione del sottospazio\n",
        "\n",
        "In questa guida illustreremo l'effetto della dimensione del sottospazio nella [tecnica di recupero della configurazione autoconsistente](https://arxiv.org/abs/2405.05068).\n",
        "\n",
        "*A priori*, non sappiamo quale sia la dimensione corretta del sottospazio necessaria per ottenere il livello di accuratezza desiderato. Tuttavia, sappiamo che aumentando la dimensione del sottospazio si aumenta la precisione del metodo. Pertanto, possiamo studiare l'accuratezza delle previsioni in funzione della dimensione del sottospazio.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a6755afb-ca1e-4473-974b-ba89acc8abce",
      "metadata": {},
      "source": [
        "Indicare la molecola e le sue proprietà.\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": [
        "Generare alcune stringhe di bit casuali per simulare i campioni della 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": [
        "Chiamare SQD man mano che le dimensioni dei lotti aumentano.\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": [
        "Questo grafico mostra che aumentando la dimensione del sottospazio si ottengono risultati più accurati.\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
}