{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Comprendere le differenze tra le opzioni a guscio aperto e a guscio chiuso e il loro effetto sulla costruzione dei sottospazi\"\n",
        "description: \"Comprendere le differenze tra le opzioni a guscio aperto e a guscio chiuso e il loro effetto sulla costruzione del sottospazio per l'ultima versione della diagonalizzazione quantistica basata su campioni (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",
        "# Comprendere le differenze tra le opzioni a guscio aperto e a guscio chiuso e il loro effetto sulla costruzione dei sottospazi\n",
        "\n",
        "In questa guida illustreremo come scegliere le dimensioni del sottospazio nel `qiskit_addon_sqd` pacchetto per la post-elaborazione di campioni quantistici utilizzando [la tecnica di recupero della configurazione auto-consistente](https://arxiv.org/abs/2405.05068).\n",
        "\n",
        "Ma soprattutto, questa guida mette in evidenza alcune differenze nel comportamento della costruzione del sottospazio quando viene eseguita in `open_shell = False` modalità o `open_shell = True` :\n",
        "\n",
        "* `open_shell = False` funziona solo quando il numero di elettroni in fase di accelerazione e di decelerazione è lo stesso.\n",
        "\n",
        "* `open_shell = True` deve essere utilizzato quando il numero di elettroni in fase di accelerazione e di decelerazione è diverso. Può essere utilizzato anche quando il numero di elettroni in fase di accelerazione e di decelerazione è lo stesso. Tuttavia, in quest’ultimo caso, vi è una differenza nelle dimensioni dei sottospazi generati tra `open_shell = False` e `open_shell = True`, come illustrato in questa guida.\n",
        "\n",
        "**NOTA:** Alcune delle manipolazioni della configurazione elettronica (stringa di bit) presenti in questo pacchetto hanno lo scopo di preservare la simmetria di spin totale $S^2$. I risolutori standard dell'interazione di configurazione selezionata (SCI) non sono in grado di garantire con esattezza la conservazione dell' $S^2$. Di conseguenza, lo fanno approssimativamente tramite un moltiplicatore di Lagrange.\n",
        "\n",
        "Anche la scelta delle configurazioni elettroniche inserite nel risolutore degli stati propri può avere un forte effetto sulla conservazione dello spin. Ad esempio, in un sistema (a 2 elettroni, 2 orbitali), è possibile campionare la configurazione $|1001\\rangle$ (che presenta una singola eccitazione di spin-up rispetto allo stato RHF $|0101\\rangle$ ), la quale è una combinazione lineare degli stati singoletto e tripletto a guscio aperto, rispettivamente $(|1001\\rangle ± |0110\\rangle) /\\sqrt{2}$. Se la configurazione |0110⟩ non viene campionata, non è possibile costruire nessuna delle funzioni proprie dello spin totale, il che porta a contaminazione o ridondanza di spin (la configurazione |1001⟩ è coinvolta in un calcolo CI, ma ha coefficiente 0 nel vettore CI). Dato che nel computer quantistico viene generato un singolo campione $|1001\\rangle$, ecco come il `sqd` pacchetto gestisce questa situazione:\n",
        "\n",
        "* `open_shell = False`:\n",
        "\n",
        "  1. La stringa di bit $1001$ viene divisa a metà, rappresentando le configurazioni \"spin-up\" e \"spin-down\": $10$ (up) e $01$ (down).\n",
        "\n",
        "  2. È stato stilato l'elenco delle configurazioni uniche con polarizzazione di spin: $\\mathcal{U} = [01, 10]$.\n",
        "\n",
        "  3. Consideriamo quindi tutte le possibili combinazioni di elementi dell’ $\\mathcal{U}$ e per formare la base: $\\left \\{ |0101\\rangle, |0110\\rangle , |1001\\rangle , |1010\\rangle \\right \\}$, che contiene gli stati singoletto e tripletto.\n",
        "\n",
        "* `open_shell = True`:\n",
        "\n",
        "  1. A differenza di quanto `open_shell = False` avviene in quel caso, non uniamo le due metà della stringa di bit per formare la base.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a6755afb-ca1e-4473-974b-ba89acc8abce",
      "metadata": {},
      "source": [
        "<span id=\"closed-shell\" />\n",
        "\n",
        "### A guscio chiuso\n",
        "\n",
        "Questo esempio illustra come vengono manipolate le stringhe di bit in un sistema (a 2 elettroni e 4 orbitali).\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": [
        "Specificare manualmente un dizionario dei risultati delle misurazioni:\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": [
        "Trasforma i conteggi `dict` in una matrice di stringhe di bit e in un array di probabilità per la post-elaborazione:\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": [
        "Creare un sottocampione di un singolo lotto di dimensione pari a due:\n",
        "\n",
        "* `n_batches = 1`: Numero di lotti di configurazioni utilizzati dalle diverse chiamate al risolutore di stati propri\n",
        "* `samples_per_batch = 2`: Numero di configurazioni uniche da includere in ogni lotto\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": [
        "Ottenere la rappresentazione decimale delle stringhe di bit \"spin-up\" e \"spin-down\" utilizzate dal risolutore degli stati propri.\n",
        "\n",
        "Il primo elemento della tupla corrisponde alla rappresentazione decimale delle configurazioni con spin verso l'alto, mentre il secondo elemento della tupla corrisponde alla rappresentazione decimale delle configurazioni con spin verso il basso:\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": [
        "Si noti che, sebbene il numero di campioni per lotto sia pari a due e le stringhe di bit campionate siano: $00010010$ e $01001000$, vengono generate quattro configurazioni elettroniche per ogni specie di spin. In questo caso, l'insieme delle configurazioni uniche con polarizzazione di spin è dato da:\n",
        "\n",
        "$$\n",
        "\\mathcal{U} = \\{ 0001, 0010, 0100, 1000 \\}\n",
        "$$\n",
        "\n",
        "la cui rappresentazione decimale base-10 è\n",
        "\n",
        "$$\n",
        "\\mathcal{U}_{10} = \\{ 1, 2, 4, 8 \\}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "03b32ed5",
      "metadata": {},
      "source": [
        "Basi del sottospazio:\n",
        "\n",
        "Il risolutore di stati propri considera tutte le possibili coppie di stringhe di bit con spin-up e spin-down per costruire la base $\\mathcal{B}$ del sottospazio:\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 dimensione del sottospazio è limitata superiormente da** : $2 \\cdot$ (`samples_per_batch`) $^2$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9412e52b",
      "metadata": {},
      "source": [
        "<span id=\"open-shell\" />\n",
        "\n",
        "### A guscio aperto\n",
        "\n",
        "Questo esempio illustra come vengono manipolate le stringhe di bit in un sistema (a 2 elettroni e 4 orbitali).\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": [
        "Specificare manualmente un dizionario dei risultati delle misurazioni:\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": [
        "Trasforma i conteggi `dict` in una matrice di stringhe di bit e in un array di probabilità per la post-elaborazione:\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": [
        "Creare un sottocampione di un singolo lotto di dimensione pari a due:\n",
        "\n",
        "* `n_batches = 1`: Numero di lotti di configurazioni utilizzati dalle diverse chiamate al risolutore di stati propri\n",
        "* `samples_per_batch = 2`: Numero di configurazioni uniche da includere in ogni lotto\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": [
        "Ottenere la rappresentazione decimale delle stringhe di bit \"spin-up\" e \"spin-down\" utilizzate dal risolutore degli stati propri.\n",
        "\n",
        "Il primo elemento della tupla corrisponde alla rappresentazione decimale delle configurazioni con spin verso l'alto, mentre il secondo elemento della tupla corrisponde alla rappresentazione decimale delle configurazioni con spin verso il basso:\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": [
        "Se specifichiamo che `open_shell = True`, non includiamo tutte le semistringhe univoche come configurazioni “spin-up” e “spin-down”, ottenendo così una base più ridotta rispetto a quando si specifica `open_shell = False`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e1959b72",
      "metadata": {},
      "source": [
        "Basi del sottospazio:\n",
        "\n",
        "Il risolutore di stati propri considera tutte le possibili coppie di stringhe di bit con spin-up e spin-down per costruire la base $\\mathcal{B}$ del sottospazio:\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 dimensione del sottospazio è limitata superiormente da** : (`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
}