From b2782dca9be51afb5e9e76809ffbb032a1a4ebdf Mon Sep 17 00:00:00 2001 From: Caleb Johnson Date: Thu, 30 Jan 2025 09:31:35 -0600 Subject: [PATCH] Use only upper triangle to define the orbital optimization rotation (#130) * Use only upper triangle to define the rotation * bugs * Fix nb, release note, style * Clean up unused var * re-run notebook * Update qiskit_addon_sqd/fermion.py Co-authored-by: Kevin J. Sung * peer review --------- Co-authored-by: Kevin J. Sung --- ...use_oo_to_optimize_hamiltonian_basis.ipynb | 112 ++---------------- qiskit_addon_sqd/fermion.py | 92 ++++++++------ .../notes/improve-oo-fcfad41b146ecea0.yaml | 4 + 3 files changed, 72 insertions(+), 136 deletions(-) create mode 100644 releasenotes/notes/improve-oo-fcfad41b146ecea0.yaml diff --git a/docs/how_tos/use_oo_to_optimize_hamiltonian_basis.ipynb b/docs/how_tos/use_oo_to_optimize_hamiltonian_basis.ipynb index 1861d6c..77e822a 100644 --- a/docs/how_tos/use_oo_to_optimize_hamiltonian_basis.ipynb +++ b/docs/how_tos/use_oo_to_optimize_hamiltonian_basis.ipynb @@ -27,33 +27,9 @@ "execution_count": 1, "id": "677f54ac-b4ed-47e3-b5ba-5366d3a520f9", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "converged SCF energy = -108.835236570775\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/caleb/venvs/blox/lib/python3.12/site-packages/numpy/linalg/linalg.py:2180: RuntimeWarning: divide by zero encountered in det\n", - " r = _umath_linalg.det(a, signature=signature)\n", - "/Users/caleb/venvs/blox/lib/python3.12/site-packages/numpy/linalg/linalg.py:2180: RuntimeWarning: invalid value encountered in det\n", - " r = _umath_linalg.det(a, signature=signature)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CASCI E = -109.046671778080 E(CI) = -32.8155692383188 S^2 = 0.0000000\n" - ] - } - ], + "outputs": [], "source": [ + "%%capture\n", "import numpy as np\n", "import pyscf\n", "import pyscf.cc\n", @@ -87,11 +63,9 @@ "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\n", - "\n", "# Rotate our integrals out of MO basis\n", - "k_rot = (np.random.rand(num_orbitals**2) - 0.5) * 0.3\n", + "num_params = (num_orbitals**2 - num_orbitals) // 2 # antisymmetric, specified by upper triangle\n", + "k_rot = (np.random.rand(num_params) - 0.5) * 0.3\n", "hcore_rot, eri_rot = rotate_integrals(hcore, eri, k_rot)" ] }, @@ -157,8 +131,8 @@ "iterations = 5\n", "\n", "# Eigenstate solver options\n", - "n_batches = 10\n", - "samples_per_batch = 300\n", + "n_batches = 3\n", + "samples_per_batch = 100\n", "max_davidson_cycles = 200\n", "\n", "# Self-consistent configuration recovery loop\n", @@ -237,66 +211,6 @@ "### Visualize the results with no orbital optimization" ] }, - { - "cell_type": "code", - "execution_count": 4, - "id": "caffd888-e89c-4aa9-8bae-4d1bb723b35e", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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VI5UyJZSPXv2xOHDh9G2bVts2rRJ1+EQERERvbKUlBTcvn1b9Tw8PByhoaGwsrKCs7Mzpk6dikePHuHnn38GACxYsABubm6oWbMm0tPT8dNPP+HgwYPYu3evahvjx4/HoEGD0KBBA/j5+WHBggVITU1VzcZHRERE9CoqZFJq7NixGDJkCNasWaPrUIiIiIhKxNmzZ9G6dWvVc+W4ToMGDUJISAgiIyNx//591frMzExMmDABjx49grGxMXx8fLB//361bfTp0wcxMTGYPn06oqKiULduXezZs0dj8HMiIiKi4qiQSalWrVrh8OHDug6DiIiIqMS0atUKQoh814eEhKg9nzx5MiZPnlzodseMGYMxY8a8anhEREREGl67MaWOHj2Kbt26wdHRERKJBFu3btUoExwcDFdXV8jlcjRq1AinT58u+0CJiIiIiIiIiKjYXrukVGpqKurUqYPg4OA812/YsAHjx4/HjBkzcP78edSpUwcBAQGIjo5Wlalbty5q1aql8Xj8+HFZHQYRERERERERERXgteu+16lTJ3Tq1Cnf9fPnz8fw4cNVA2wuW7YMu3btwqpVqzBlyhQAuTPHlJSMjAxkZGSoniclJZXYtomIiIiIiIiIKqrXrqVUQTIzM3Hu3Dm0a9dOtUxPTw/t2rXDyZMnS2Wfc+bMgUKhUD2cnJxKZT9ERERERERERBXJG5WUevr0KbKzszVmfLGzs0NUVJTW22nXrh3effdd7N69G1WqVCkwoTV16lQkJiaqHg8ePCh2/ERERERERERElOu1675XFvbv3691WZlMBplMVorREBERERERERFVPG9USylra2tIpVI8efJEbfmTJ09gb2+vo6iIiIiIiIiIiKio3qiklKGhIXx9fXHgwAHVspycHBw4cAD+/v46jIyIiIiIiIiIiIriteu+l5KSgtu3b6ueh4eHIzQ0FFZWVnB2dsb48eMxaNAgNGjQAH5+fliwYAFSU1NVs/GVluDgYAQHByM7O7tU90NEREREREREVBG8dkmps2fPonXr1qrn48ePBwAMGjQIISEh6NOnD2JiYjB9+nRERUWhbt262LNnj8bg5yUtKCgIQUFBSEpKgkKhKNV9ERERERERERGVd69dUqpVq1YQQhRYZsyYMRgzZkwZRURERERERERERCXtjRpTioiIiIiIiIiIygcmpYiIiIiIiIiIqMwxKUVERERERERERGWOSSktBQcHw9vbGw0bNtR1KEREREREREREbzwmpbQUFBSEsLAwnDlzRtehEBERERERERG98ZiUIiIiIiIiIiKiMsekFBERERERERERlTkmpYiIiIiIiIiIqMwxKUVERERERERERGWOSSkiIiIiIiIiIipzTEppKTg4GN7e3mjYsKGuQyEiIiIiIiIieuMxKaWloKAghIWF4cyZM7oOhYiIiIiIiIjojcekFBERERERERERlTkmpYiIiIiIiIiIqMwxKUVERERERERERGWOSSkiIiIiIiIiIipzTEoREREREREREVGZY1KKiIiIiIiIiIjKHJNSWgoODoa3tzcaNmyo61CIiIiIiIiIiN54TEppKSgoCGFhYThz5oyuQyEiIiIiIiIieuMxKUVERERERERERGWOSSkiIiIiIiIiIipzTEoREREREREREVGZY1KKiIiIiIiIiIjKHJNSRERERERERERU5piUIiIiIiIiIiKiMsekFBERERERERERlTn9V3nx06dP8fTpU0gkElhbW6NSpUolFRcREREREREREZVjRUpKpaamYuPGjdi2bRtOnDiBp0+fqq23traGv78/evTogXfffRcmJiYlGqwuBQcHIzg4GNnZ2boOhYiIiIiIiIjojadVUio2NhZz5szB8uXLkZ6eDh8fH7z11ltwd3eHpaUlhBCIj49HeHg4zp07h+HDh+PDDz/EyJEjMWXKFFhbW5f2cZS6oKAgBAUFISkpCQqFQtfhEBERERERERG90bRKSrm6uqJq1ar45ptv8M4778DGxqbA8jExMdi8eTNWrFiBFStWICkpqUSCJSIiIiIiIiKi8kGrpNSmTZsQEBCg9UZtbGwwatQojBo1Cn/99VexgyMiIiIiIiIiovJJq9n3ipKQKsnXEhERERERERFR+aRVUoqIiIiIiIiIiKgkFWn2vRelp6dj8+bNOH/+PBITE5GTk6O2XiKRYOXKla8cIBEREVF58s8//6BRo0a6DoOIiIhI54qVlLp37x5at26NiIgIWFhYIDExEVZWVkhISEB2djasra1hampa0rESERERvfH8/f1RtWpVDBgwAP3794e7u7uuQyIiIiLSiWJ135s0aRISExNx6tQp3Lx5E0IIbNiwASkpKZg3bx6MjIw4wDkRERFRHtatWwdPT0/Mnj0bnp6eaNq0KZYtW4a4uDhdh0ZERERUpoqVlDp48CA++OAD+Pn5QU8vdxNCCMhkMkyaNAlt27bFuHHjSjJOIiIionLhvffew65du/D48WMsXLgQQgh88MEHcHR0RI8ePbBp0yZkZmbqOkwiIiKiUlespFRaWhpcXV0BAObm5pBIJEhMTFSt9/f3x7Fjx0okQCIiIqLyyNraGmPGjMGJEydw69YtfPbZZ7h+/Tr69OkDe3t7jBgxgvUpIiIiKteKlZRydnbGw4cPAQD6+vqoXLkyTp06pVofFhYGuVxeMhG+JoKDg+Ht7Y2GDRvqOhQiIiIqZ4yMjGBsbAy5XA4hBCQSCbZt24aWLVuiYcOGCAsLK3QbR48eRbdu3eDo6AiJRIKtW7cWWH7Lli1o3749bGxsYG5uDn9/f43hF2bOnAmJRKL28PLyepVDJSIiIlIpVlKqTZs22LZtm+p5YGAgvv/+ewwfPhxDhw5FcHAwunXrVmJBvg6CgoIQFhaGM2fO6DoUIiIiKgeSk5OxevVqtGvXDi4uLvj000/h6uqKTZs2ISoqCo8fP8aGDRsQHR2NwYMHF7q91NRU1KlTB8HBwVrt/+jRo2jfvj12796Nc+fOoXXr1ujWrRsuXLigVq5mzZqIjIxUPdh6i4iIiEpKsWbfmzJlCs6cOYOMjAzIZDJ8+umnePz4MTZt2gSpVIr33nsP8+fPL+lYiYiIiN5427Ztw/r167Fz506kp6ejYcOGWLBgAfr27YtKlSqple3Vqxfi4+MRFBRU6HY7deqETp06aR3HggUL1J5/9dVX2LZtG3bs2IF69eqpluvr68Pe3l7r7RIRERFpq1hJKWdnZzg7O6uey+Vy/PTTT/jpp59KLDAiIiKi8qhnz55wcnLCxx9/jIEDB6J69eoFlq9Tpw769+9f6nHl5OQgOTkZVlZWastv3boFR0dHyOVy+Pv7Y86cOWr1wJdlZGQgIyND9TwpKanUYiYiIqI3W7GSUkRERERUPAcPHkSrVq20Lu/n5wc/P7/SC+hf3377LVJSUtC7d2/VskaNGiEkJATVq1dHZGQkZs2ahebNm+PKlSswMzPLcztz5szBrFmzSj1eIiIievNpnZTasmVLkTf+9ttvF/k1REREROVZURJSZeWXX37BrFmzsG3bNtja2qqWv9gd0MfHB40aNYKLiwt+//13DB06NM9tTZ06FePHj1c9T0pKgpOTU+kFT0RERG8srZNSvXr1gkQigRBCtUwikQCA2rIX12VnZ5dAiERERETlx//+9z/s3LkToaGhea6vV68eevTogRkzZpRJPL/99huGDRuGjRs3ol27dgWWtbCwQLVq1XD79u18y8hkMshkspIOk4iIiMohrZNShw4dUnuekJCAnj174ttvv4Wvr2+JB0ZERERUHm3atAk9e/bMd33nzp2xYcOGMklK/frrrxgyZAh+++03dOnSpdDyKSkpuHPnDgYMGFDqsREREVH5p3VSqmXLlmrPY2NjAQB169bVWEdEREREebt//z48PDzyXe/m5oZ79+4VebspKSlqLZjCw8MRGhoKKysrODs7Y+rUqXj06BF+/vlnALld9gYNGoSFCxeiUaNGiIqKAgAYGRlBoVAAACZOnIhu3brBxcUFjx8/xowZMyCVStGvX78ix0dERET0Mj1dB0BERERUkZiamhaYdAoPD4dcLi/yds+ePYt69eqhXr16AIDx48ejXr16mD59OgAgMjIS9+/fV5VfsWIFsrKyEBQUBAcHB9Vj7NixqjIPHz5Ev379UL16dfTu3RuVKlXCqVOnYGNjU+T4iIiIiF7G2feIiIiIylCrVq2wfPlyjBo1CpUrV1Zb9+DBA6xYsQKtW7cu1nbzGudTKSQkRO354cOHC93mb7/9VuQ4iIiIiLTFpBQRERFRGZo9ezb8/PxQs2ZNDB06FDVr1gQAXLlyBatWrYIQArNnz9ZxlERERESl75WTUsoZ+IiIiIiocNWrV8fff/+NDz/8EN9//73auhYtWuCHH35AjRo1dBQdERERUdnROinVvXt3tefPnz8HAHz22WewtrbWKC+RSLBt27ZXDI+IiIio/PHx8cGRI0fw9OlT3L17FwDg7u6eZ52KiIiIqLzSOil16dIljVZRLi4uiIyMRGRkpEZ5tqAiIiIiKpi1tTUTUURERFRhaZ2UioiIKMUwXn/BwcEIDg5Gdna2rkMhIiKiN1x2djb++usv3L17F/Hx8RoDlEskEkybNk1H0RERERGVDQ50rqWgoCAEBQUhKSkJCoVC1+EQERHRG+rs2bN455138PDhw3xny2NSioiIiCoCPW0KpaWlFXsHr/JaIiIiovLmgw8+wLNnz7B161bExcUhJydH48GW2URERFQRaJWUcnJywueff57n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WVkFrt+/f7+qVKnicFIAAAClVfny5dW/f3+tWLFCGRkZmj17tqpXr66JEycqPDxcEREReumll1ydJgAAgNM5VJTq2LGjFixYoEuXLuVZl56erjlz5qhz5843nFxxkpiYqPDwcLVs2dLVqQAAgFKiYsWKeuSRR7Ry5UodPnxYr776qtLS0vT888+7OjUAAACn83BkoxdffFG33XabWrZsqd69e8tisWjlypX6+uuv9fbbb8swDMXHxxd1ri5ltVpltVqVmZkpX19fV6cDAABKiYsXL+rLL7/U4sWLtXz5cp09e1Y1atRwdVoAAABO59CVUvXr19f69etVpUoVjR07VoZh6OWXX9bkyZPVpEkTffvttwoNDS3iVAEAAEqHS5cu6YsvvlBsbKyqVq2qHj16aO3atRo4cKDWr1+vgwcPujpFAAAAp3PoSilJatSokb766iudPHlSe/fuVW5urmrVqqWqVasWZX4AAAClyiOPPKJly5bp5MmT8vPzU9++fRUTE6M777xTFovF1ekBAACYxuGi1GWVKlViniUAAIBCWrZsmf75z3+qT58+uuuuu+Tu7p4n5uTJk6pUqZILsgMAADCPw0WpnJwcrVy5Uvv379fJkydlGIbdeovForFjx95wggAAAKVJRkaGPDzyDsGys7P12WefaeHChUpKStL58+ddkB0AAIB5HCpKbdmyRffff79+//33PMWoyyhKAQAA5HVlQcowDCUnJ2vhwoVaunSpMjMzVbVqVT344IMuzBAAAMAcDhWlhg0bpj///FPLli1Tu3btVLFixSJOCwAAoPTaunWrFi5cqEWLFik9PV0Wi0UxMTEaPny4brvtNuaWAgAANwWHilLbt2/Xiy++qO7duxd1PgAAAKXS/v37tXDhQi1cuFB79uxRtWrV1K9fP7Vq1Up9+vTR/fffrzZt2rg6TQAAANM4VJSqXr16gbftAQAAwF6bNm20efNm+fn5qVevXnrnnXfUtm1bSdK+fftcnB0AAIBruDmy0TPPPKM5c+YoMzOzqPMBAAAodTZt2qTQ0FDNnj1b06dPtxWkAAAAbmYOXSl15swZ3XLLLapTp45iYmJUo0aNPI8ztlgsGjlyZJEkCQAAUJLNmDFDH3zwgf75z3+qcuXKuv/++xUTE6MOHTq4OjUAAACXcago9dRTT9n+P2PGjHxjSltRKjExUYmJ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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "# Data for energies plot\n", - "x1 = range(iterations)\n", - "e_diff = [abs(np.min(energies) - exact_energy) for energies in e_hist]\n", - "yt1 = [1.0, 1e-1, 1e-2, 1e-3, 1e-4]\n", - "\n", - "# Chemical accuracy (+/- 1 milli-Hartree)\n", - "chem_accuracy = 0.001\n", - "\n", - "# Data for avg spatial orbital occupancy\n", - "y2 = avg_occupancy[:num_orbitals] + avg_occupancy[num_orbitals:]\n", - "x2 = range(len(y2))\n", - "\n", - "fig, axs = plt.subplots(1, 2, figsize=(12, 6))\n", - "\n", - "# Plot energies\n", - "axs[0].plot(x1, e_diff, label=\"energy error\", marker=\"o\")\n", - "axs[0].set_xticks(x1)\n", - "axs[0].set_xticklabels(x1)\n", - "axs[0].set_yticks(yt1)\n", - "axs[0].set_yticklabels(yt1)\n", - "axs[0].set_yscale(\"log\")\n", - "axs[0].set_ylim(1e-4)\n", - "axs[0].axhline(y=chem_accuracy, color=\"#BF5700\", linestyle=\"--\", label=\"chemical accuracy\")\n", - "axs[0].set_title(\"Approximated Ground State Energy Error vs SQD Iterations\")\n", - "axs[0].set_xlabel(\"Iteration Index\", fontdict={\"fontsize\": 12})\n", - "axs[0].set_ylabel(\"Energy Error (Ha)\", fontdict={\"fontsize\": 12})\n", - "axs[0].legend()\n", - "\n", - "# Plot orbital occupancy\n", - "axs[1].bar(x2, y2, width=0.8)\n", - "axs[1].set_xticks(x2)\n", - "axs[1].set_xticklabels(x2)\n", - "axs[1].set_title(\"Avg Occupancy per Spatial Orbital\")\n", - "axs[1].set_xlabel(\"Orbital Index\", fontdict={\"fontsize\": 12})\n", - "axs[1].set_ylabel(\"Avg Occupancy\", fontdict={\"fontsize\": 12})\n", - "\n", - "plt.tight_layout()\n", - "plt.show()" - ] - }, { "cell_type": "markdown", "id": "e8c6d5e4", @@ -349,7 +263,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "id": "2a587030", "metadata": {}, "outputs": [ @@ -357,8 +271,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Subspace dimension: 213444\n", - "Energy of that batch from SQD: -108.87152693374452\n" + "Subspace dimension: 32041\n", + "Energy of that batch from SQD: -109.13624164091385\n" ] } ], @@ -383,14 +297,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 5, "id": "b5e56baf", "metadata": {}, "outputs": [], "source": [ "from qiskit_addon_sqd.fermion import optimize_orbitals\n", "\n", - "k_flat = (np.random.rand(num_orbitals**2) - 0.5) * 0.01 # initial guess for rotation params\n", + "k_flat = (np.random.rand(num_params) - 0.5) * 0.01\n", "num_iters = 20\n", "num_steps_grad = 10_000 # relatively cheap to execute\n", "learning_rate = 0.05\n", @@ -419,7 +333,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "id": "78a80e64", "metadata": {}, "outputs": [ @@ -427,7 +341,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "improved_energy in the new basis: -108.87267142096594\n" + "improved_energy in the new basis: -109.1429260747482\n" ] } ], diff --git a/qiskit_addon_sqd/fermion.py b/qiskit_addon_sqd/fermion.py index 1d6c5b6..adba3dd 100644 --- a/qiskit_addon_sqd/fermion.py +++ b/qiskit_addon_sqd/fermion.py @@ -202,9 +202,8 @@ def optimize_orbitals( two lists should represent the spin-up and spin-down orbitals, respectively. hcore: Core Hamiltonian matrix representing single-electron integrals eri: Electronic repulsion integrals representing two-electron integrals - k_flat: 1D array defining the orbital transform. This array will be reshaped - to be of shape (# orbitals, # orbitals) before being used as a - similarity transform operator on the orbitals. Thus ``len(k_flat)=# orbitals**2``. + k_flat: 1D array defining the orbital transform, ``K``. The array should specify the upper + triangle of the anti-symmetric transform operator in row-major order, excluding the diagonal. open_shell: A flag specifying whether configurations from the left and right halves of the bitstrings should be kept separate. If ``False``, CI strings from the left and right halves of the bitstrings are combined into a single @@ -223,6 +222,13 @@ def optimize_orbitals( - Average orbital occupancy """ + norb = hcore.shape[0] + num_params = (norb**2 - norb) // 2 + if len(k_flat) != num_params: + raise ValueError( + f"k_flat must specify the upper triangle of the transform matrix. k_flat length is {len(k_flat)}. " + f"Expected {num_params}." + ) if isinstance(bitstring_matrix, tuple): warnings.warn( "Passing a length-2 tuple of determinant lists to define the spin-up/down subspaces " @@ -240,7 +246,6 @@ def optimize_orbitals( # TODO: Need metadata showing the optimization history ## hcore and eri in physicist ordering - num_orbitals = hcore.shape[0] k_flat = k_flat.copy() eri_phys = np.asarray(eri.transpose(0, 2, 3, 1), order="C") # physicist ordering for _ in range(num_iters): @@ -255,16 +260,16 @@ def optimize_orbitals( myci, hcore_rot, eri_rot_chem, - num_orbitals, + norb, (num_up, num_dn), ci_strs=ci_strs, max_cycle=max_davidson, ) # Generate the one and two-body reduced density matrices from latest wavefunction amplitudes - dm1, dm2_chem = myci.make_rdm12(amplitudes, num_orbitals, (num_up, num_dn)) + dm1, dm2_chem = myci.make_rdm12(amplitudes, norb, (num_up, num_dn)) dm2 = np.asarray(dm2_chem.transpose(0, 2, 3, 1), order="C") - dm1a, dm1b = myci.make_rdm1s(amplitudes, num_orbitals, (num_up, num_dn)) + dm1a, dm1b = myci.make_rdm1s(amplitudes, norb, (num_up, num_dn)) # TODO: Expose the momentum parameter as an input option # Optimize the basis rotations @@ -292,17 +297,22 @@ def rotate_integrals( Args: hcore: Core Hamiltonian matrix representing single-electron integrals eri: Electronic repulsion integrals representing two-electron integrals - k_flat: 1D array defining the orbital transform. Refer to `Sec. II A 4 `_ - for more information on how these values are used to generate the transform operator. + k_flat: 1D array defining the orbital transform, ``K``. The array should specify the upper + triangle of the anti-symmetric transform operator in row-major order, excluding the diagonal. Returns: - The rotated core Hamiltonian matrix - The rotated ERI matrix """ - num_orbitals = hcore.shape[0] - p = np.reshape(k_flat, (num_orbitals, num_orbitals)) - K = (p - np.transpose(p)) / 2.0 + norb = hcore.shape[0] + num_params = (norb**2 - norb) // 2 + if len(k_flat) != num_params: + raise ValueError( + f"k_flat must specify the upper triangle of the transform matrix. k_flat length is {len(k_flat)}. " + f"Expected {num_params}." + ) + K = _antisymmetric_matrix_from_upper_tri(k_flat, norb) U = LA.expm(K) hcore_rot = np.matmul(np.transpose(U), np.matmul(hcore, U)) eri_rot = np.einsum("pqrs, pi, qj, rk, sl->ijkl", eri, U, U, U, U, optimize=True) @@ -323,12 +333,12 @@ def flip_orbital_occupancies(occupancies: np.ndarray) -> np.ndarray: where ``N`` is the number of spatial orbitals. """ - num_orbitals = occupancies.shape[0] // 2 - occ_up = occupancies[:num_orbitals] - occ_dn = occupancies[num_orbitals:] - occ_out = np.zeros(2 * num_orbitals) - occ_out[:num_orbitals] = np.flip(occ_up) - occ_out[num_orbitals:] = np.flip(occ_dn) + norb = occupancies.shape[0] // 2 + occ_up = occupancies[:norb] + occ_dn = occupancies[norb:] + occ_out = np.zeros(2 * norb) + occ_out[:norb] = np.flip(occ_up) + occ_out[norb:] = np.flip(occ_dn) return occ_out @@ -363,19 +373,19 @@ def bitstring_matrix_to_sorted_addresses( right (spin-up) halves of the bitstrings, respectively. """ - num_orbitals = bitstring_matrix.shape[1] // 2 + norb = bitstring_matrix.shape[1] // 2 num_configs = bitstring_matrix.shape[0] address_left = np.zeros(num_configs) address_right = np.zeros(num_configs) - bts_matrix_left = bitstring_matrix[:, :num_orbitals] - bts_matrix_right = bitstring_matrix[:, num_orbitals:] + bts_matrix_left = bitstring_matrix[:, :norb] + bts_matrix_right = bitstring_matrix[:, norb:] # For performance, we accumulate the left and right addresses together, column-wise, # across the two halves of the input bitstring matrix. - for i in range(num_orbitals): - address_left[:] += bts_matrix_left[:, i] * 2 ** (num_orbitals - 1 - i) - address_right[:] += bts_matrix_right[:, i] * 2 ** (num_orbitals - 1 - i) + for i in range(norb): + address_left[:] += bts_matrix_left[:, i] * 2 ** (norb - 1 - i) + address_right[:] += bts_matrix_right[:, i] * 2 ** (norb - 1 - i) addresses_right = np.unique(address_right.astype("longlong")) addresses_left = np.unique(address_left.astype("longlong")) @@ -410,19 +420,19 @@ def bitstring_matrix_to_ci_strs( halves of the bitstrings, respectively. """ - num_orbitals = bitstring_matrix.shape[1] // 2 + norb = bitstring_matrix.shape[1] // 2 num_configs = bitstring_matrix.shape[0] ci_str_left = np.zeros(num_configs) ci_str_right = np.zeros(num_configs) - bts_matrix_left = bitstring_matrix[:, :num_orbitals] - bts_matrix_right = bitstring_matrix[:, num_orbitals:] + bts_matrix_left = bitstring_matrix[:, :norb] + bts_matrix_right = bitstring_matrix[:, norb:] # For performance, we accumulate the left and right CI strings together, column-wise, # across the two halves of the input bitstring matrix. - for i in range(num_orbitals): - ci_str_left[:] += bts_matrix_left[:, i] * 2 ** (num_orbitals - 1 - i) - ci_str_right[:] += bts_matrix_right[:, i] * 2 ** (num_orbitals - 1 - i) + for i in range(norb): + ci_str_left[:] += bts_matrix_left[:, i] * 2 ** (norb - 1 - i) + ci_str_right[:] += bts_matrix_right[:, i] * 2 ** (norb - 1 - i) ci_strs_right = np.unique(ci_str_right.astype("longlong")) ci_strs_left = np.unique(ci_str_left.astype("longlong")) @@ -459,6 +469,17 @@ def enlarge_batch_from_transitions( return np.array(bitstring_matrix_augmented) +def _antisymmetric_matrix_from_upper_tri(k_flat: np.ndarray, k_dim: int) -> Array: + """Create an anti-symmetric matrix given the upper triangle.""" + K = jnp.zeros((k_dim, k_dim)) + upper_indices = jnp.triu_indices(k_dim, k=1) + lower_indices = jnp.tril_indices(k_dim, k=-1) + K = K.at[upper_indices].set(k_flat) + K = K.at[lower_indices].set(-k_flat) + + return K + + def _check_ci_strs( ci_strs: tuple[np.ndarray, np.ndarray], ) -> tuple[np.ndarray, np.ndarray]: @@ -499,9 +520,8 @@ def _optimize_orbitals_sci( This procedure is described in `Sec. II A 4 `_. """ prev_update = np.zeros(len(k_flat)) - num_orbitals = dm1.shape[0] for _ in range(num_steps): - grad = _SCISCF_Energy_contract_grad(dm1, dm2, hcore, eri, num_orbitals, k_flat) + grad = _SCISCF_Energy_contract_grad(dm1, dm2, hcore, eri, k_flat) prev_update = learning_rate * grad + momentum * prev_update k_flat -= prev_update @@ -511,7 +531,6 @@ def _SCISCF_Energy_contract( dm2: np.ndarray, hcore: np.ndarray, eri: np.ndarray, - num_orbitals: int, k_flat: np.ndarray, ) -> Array: """Calculate gradient. @@ -520,8 +539,7 @@ def _SCISCF_Energy_contract( reduced density matrices with the gradients of the of the one and two-body integrals with respect to the rotation parameters, ``k_flat``. """ - p = jnp.reshape(k_flat, (num_orbitals, num_orbitals)) - K = (p - jnp.transpose(p)) / 2.0 + K = _antisymmetric_matrix_from_upper_tri(k_flat, hcore.shape[0]) U = expm(K) hcore_rot = jnp.matmul(jnp.transpose(U), jnp.matmul(hcore, U)) eri_rot = jnp.einsum("pqrs, pi, qj, rk, sl->ijkl", eri, U, U, U, U) @@ -530,12 +548,12 @@ def _SCISCF_Energy_contract( return grad -_SCISCF_Energy_contract_grad = jit(grad(_SCISCF_Energy_contract, argnums=5), static_argnums=4) +_SCISCF_Energy_contract_grad = jit(grad(_SCISCF_Energy_contract, argnums=4)) def _apply_excitation_single( single_bts: np.ndarray, diag: np.ndarray, create: np.ndarray, annihilate: np.ndarray -) -> tuple[jnp.ndarray, Array]: +) -> tuple[Array, Array]: falses = jnp.array([False for _ in range(len(diag))]) bts_ret = single_bts == diag diff --git a/releasenotes/notes/improve-oo-fcfad41b146ecea0.yaml b/releasenotes/notes/improve-oo-fcfad41b146ecea0.yaml new file mode 100644 index 0000000..0d4f4df --- /dev/null +++ b/releasenotes/notes/improve-oo-fcfad41b146ecea0.yaml @@ -0,0 +1,4 @@ +--- +upgrade: + - | + :func:`qiskit_addon_sqd.fermion.optimize_orbitals` and :func:`qiskit_addon_sqd.fermion.rotate_integrals` now require ``k_flat`` to specify the upper triangle (not including diagonal) of the rotation matrix, rather than the entire matrix.