{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Add fermionic transitions to the pool of configurations\"\n",
        "description: \"Add fermionic transitions to the pool of configurations for the latest version of Sample-based quantum diagonalization (SQD)\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9e40af77-7f0f-4dd6-ab0a-420cf396050e",
      "metadata": {},
      "source": [
        "# Add fermionic transitions to the pool of configurations\n",
        "\n",
        "Here we demonstrate the functionalities to augment the pool of electronic\n",
        "configurations obtained by the action of transition operators on each electronic\n",
        "configuration.\n",
        "\n",
        "We demonstrate how to add single-electron hops of the type:\n",
        "\n",
        "$$\n",
        "c^\\dagger_{p\\sigma} c_{q\\sigma} |\\textbf{x} \\rangle\n",
        "$$\n",
        "\n",
        "for $p, q = 1, ..., N_\\textrm{orb}$ and $\\sigma \\in \\{ \\uparrow, \\downarrow\\}$,\n",
        "and for all $|\\textbf{x} \\rangle$ in the batch of electronic configurations.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0a7e9fcd",
      "metadata": {},
      "source": [
        "We start by generating a batch of random electronic configurations:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "e9506e0b-ed64-48bb-a97a-ef851b604af1",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "\n",
        "n_qubits = 8\n",
        "n_orb = n_qubits // 2\n",
        "\n",
        "rand_seed = 22\n",
        "np.random.seed(rand_seed)\n",
        "\n",
        "\n",
        "# Generate some random bitstrings for testing\n",
        "def random_bitstrings(n_samples, n_qubits):\n",
        "    return (\n",
        "        np.round(np.random.rand(n_samples, n_qubits))\n",
        "        .astype(\"int\")\n",
        "        .astype(\"bool\")\n",
        "    )\n",
        "\n",
        "\n",
        "bitstring_matrix = random_bitstrings(100, n_qubits)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4155599f",
      "metadata": {},
      "source": [
        "The excitation operators are specified inside a numpy array whose length is\n",
        "equal to the number of fermionic nodes (or qubits). Each element of the array\n",
        "must be a string that can take values:\n",
        "\n",
        "* `'I'`: Identity\n",
        "* `'+'`: Creation operator\n",
        "* `'-'`: Annihilation operator\n",
        "\n",
        "We generate all possible single-electron transitions (amongst same spin\n",
        "species).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "389284f3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[['I' 'I' 'I' 'I' 'I' 'I' 'I' 'I']\n",
            " ['+' '-' 'I' 'I' 'I' 'I' 'I' 'I']\n",
            " ['-' '+' 'I' 'I' 'I' 'I' 'I' 'I']\n",
            " ['I' 'I' 'I' 'I' '+' '-' 'I' 'I']\n",
            " ['I' 'I' 'I' 'I' '-' '+' 'I' 'I']\n",
            " ['+' 'I' '-' 'I' 'I' 'I' 'I' 'I']\n",
            " ['-' 'I' '+' 'I' 'I' 'I' 'I' 'I']\n",
            " ['I' 'I' 'I' 'I' '+' 'I' '-' 'I']\n",
            " ['I' 'I' 'I' 'I' '-' 'I' '+' 'I']\n",
            " ['+' 'I' 'I' '-' 'I' 'I' 'I' 'I']\n",
            " ['-' 'I' 'I' '+' 'I' 'I' 'I' 'I']\n",
            " ['I' 'I' 'I' 'I' '+' 'I' 'I' '-']\n",
            " ['I' 'I' 'I' 'I' '-' 'I' 'I' '+']\n",
            " ['I' '+' '-' 'I' 'I' 'I' 'I' 'I']\n",
            " ['I' '-' '+' 'I' 'I' 'I' 'I' 'I']\n",
            " ['I' 'I' 'I' 'I' 'I' '+' '-' 'I']\n",
            " ['I' 'I' 'I' 'I' 'I' '-' '+' 'I']\n",
            " ['I' '+' 'I' '-' 'I' 'I' 'I' 'I']\n",
            " ['I' '-' 'I' '+' 'I' 'I' 'I' 'I']\n",
            " ['I' 'I' 'I' 'I' 'I' '+' 'I' '-']\n",
            " ['I' 'I' 'I' 'I' 'I' '-' 'I' '+']\n",
            " ['I' 'I' '+' '-' 'I' 'I' 'I' 'I']\n",
            " ['I' 'I' '-' '+' 'I' 'I' 'I' 'I']\n",
            " ['I' 'I' 'I' 'I' 'I' 'I' '+' '-']\n",
            " ['I' 'I' 'I' 'I' 'I' 'I' '-' '+']]\n"
          ]
        }
      ],
      "source": [
        "transitions_single = np.array(\n",
        "    [\n",
        "        [\"I\" for i in range(2 * n_orb)]\n",
        "        for j in range(4 * (n_orb**2 - n_orb) // 2 + 1)\n",
        "    ]\n",
        ")\n",
        "count = 1\n",
        "for i in range(n_orb):\n",
        "    for j in range(i + 1, n_orb):\n",
        "        # spin up\n",
        "        transitions_single[count, i] = \"+\"\n",
        "        transitions_single[count, j] = \"-\"\n",
        "        count += 1\n",
        "        transitions_single[count, i] = \"-\"\n",
        "        transitions_single[count, j] = \"+\"\n",
        "        count += 1\n",
        "\n",
        "        # spin down\n",
        "        transitions_single[count, i + n_orb] = \"+\"\n",
        "        transitions_single[count, j + n_orb] = \"-\"\n",
        "        count += 1\n",
        "        transitions_single[count, i + n_orb] = \"-\"\n",
        "        transitions_single[count, j + n_orb] = \"+\"\n",
        "        count += 1\n",
        "\n",
        "print(transitions_single)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c15c5b3f",
      "metadata": {},
      "source": [
        "Now we apply the transition operators to the configurations in `bitstring_matrix`:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "6a44f358",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "(723, 8)\n",
            "[[False False False ... False False  True]\n",
            " [False  True False ...  True False False]\n",
            " [ True  True  True ...  True False  True]\n",
            " ...\n",
            " [ True False  True ... False False  True]\n",
            " [ True  True  True ...  True False  True]\n",
            " [False False False ... False False  True]]\n"
          ]
        }
      ],
      "source": [
        "from qiskit_addon_sqd.fermion import enlarge_batch_from_transitions\n",
        "\n",
        "bitstring_matrix_aug = enlarge_batch_from_transitions(\n",
        "    bitstring_matrix, transitions_single\n",
        ")\n",
        "\n",
        "print(bitstring_matrix_aug.shape)\n",
        "print(bitstring_matrix_aug)"
      ]
    },
    {
      "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
}