Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate determinant addresses as input to fermionic solver functions #29

Merged
merged 9 commits into from
Sep 18, 2024
3 changes: 2 additions & 1 deletion docs/how_tos/choose_subspace_dimension.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,10 @@
" addresses = bitstring_matrix_to_sorted_addresses(batches[j], open_shell=open_shell)\n",
" int_d[j] = len(addresses[0]) * len(addresses[1])\n",
" energy_sci, coeffs_sci, avg_occs, spin = solve_fermion(\n",
" addresses,\n",
" batches[j],\n",
" hcore,\n",
" eri,\n",
" open_shell=open_shell,\n",
" spin_sq=spin_sq,\n",
" max_davidson=max_davidson_cycles,\n",
" )\n",
Expand Down
2 changes: 1 addition & 1 deletion docs/how_tos/select_open_closed_shell.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"source": [
"# Understand open-shell vs closed-shell options and its effect in the subspace construction\n",
"\n",
"In this \"how-to\", we will show how to choose subpace dimensions in the `sqd` package to post-process quantum samples using the [self-consistent configuration recovery technique](https://arxiv.org/abs/2405.05068). \n",
"In this \"how-to\", we will show how to choose subpace dimensions in the `qiskit_addon_sqd` package to post-process quantum samples using the [self-consistent configuration recovery technique](https://arxiv.org/abs/2405.05068). \n",
"\n",
"More importantly, this \"how-to\" also highlights some differences in the behaviour in the susbapce construction when run in `open_shell = False` or `open_shell = True` modes:\n",
"\n",
Expand Down
32 changes: 13 additions & 19 deletions docs/how_tos/use_oo_to_optimize_hamiltonian_basis.ipynb

Large diffs are not rendered by default.

11 changes: 5 additions & 6 deletions docs/tutorials/01_chemistry_hamiltonian.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"Overwritten attributes get_ovlp get_hcore of <class 'pyscf.scf.hf_symm.SymAdaptedRHF'>\n"
"Overwritten attributes get_hcore get_ovlp of <class 'pyscf.scf.hf_symm.SymAdaptedRHF'>\n"
]
}
],
Expand Down Expand Up @@ -236,8 +236,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Gate counts (w/o pre-init passes): OrderedDict({'rz': 7402, 'sx': 6009, 'ecr': 2232, 'x': 317, 'measure': 32, 'barrier': 1})\n",
"Gate counts (w/ pre-init passes): OrderedDict({'rz': 4158, 'sx': 3186, 'ecr': 1262, 'x': 210, 'measure': 32, 'barrier': 1})\n"
"Gate counts (w/o pre-init passes): OrderedDict({'rz': 7403, 'sx': 6014, 'ecr': 2232, 'x': 315, 'measure': 32, 'barrier': 1})\n",
"Gate counts (w/ pre-init passes): OrderedDict({'rz': 4160, 'sx': 3184, 'ecr': 1262, 'x': 209, 'measure': 32, 'barrier': 1})\n"
]
}
],
Expand Down Expand Up @@ -372,7 +372,6 @@
"source": [
"from qiskit_addon_sqd.configuration_recovery import recover_configurations\n",
"from qiskit_addon_sqd.fermion import (\n",
" bitstring_matrix_to_sorted_addresses,\n",
" flip_orbital_occupancies,\n",
" solve_fermion,\n",
")\n",
Expand Down Expand Up @@ -427,11 +426,11 @@
" occs_tmp = np.zeros((n_batches, 2 * num_orbitals))\n",
" coeffs = []\n",
" for j in range(n_batches):\n",
" addresses = bitstring_matrix_to_sorted_addresses(batches[j], open_shell=open_shell)\n",
" energy_sci, coeffs_sci, avg_occs, spin = solve_fermion(\n",
" addresses,\n",
" batches[j],\n",
" hcore,\n",
" eri,\n",
" open_shell=open_shell,\n",
" spin_sq=spin_sq,\n",
" max_davidson=max_davidson_cycles,\n",
" )\n",
Expand Down
82 changes: 63 additions & 19 deletions qiskit_addon_sqd/fermion.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

from __future__ import annotations

import warnings

import numpy as np
from jax import Array, config, grad, jit, vmap
from jax import numpy as jnp
Expand All @@ -39,28 +41,36 @@


def solve_fermion(
addresses: tuple[np.ndarray, np.ndarray],
bitstring_matrix: tuple[np.ndarray, np.ndarray] | np.ndarray,
kevinsung marked this conversation as resolved.
Show resolved Hide resolved
/,
hcore: np.ndarray,
eri: np.ndarray,
*,
addresses: tuple[np.ndarray, np.ndarray] | None = None,
open_shell: bool = False,
spin_sq: int | None = None,
max_davidson: int = 100,
verbose: int | None = None,
) -> tuple[float, np.ndarray, list[np.ndarray], float]:
"""
Approximate the ground state given molecular integrals and Slater determinant addresses.

.. note::
The ``addresses`` are expected to be unique and sorted. While this will be handled
for the user automatically, this function could become slower if the input
addresses are not sorted or nearly-sorted.
Approximate the ground state given molecular integrals and a set of electronic configurations.

Args:
addresses: A length-2 tuple of 1D arrays containing sorted, base-10
representations of bitstrings. The first array represents configurations of the
alpha particles, and the second array represents that of the beta particles.
bitstring_matrix: A set of configurations defining the subspace onto which the Hamiltonian
will be projected and diagonalized. This may be specified with a bitstring matrix -- a
2D array of bool representations of bit values such that each row represents a single
bitstring. The spin-up configurations should be specified by column indices in range
``(N, N/2]``, and the spin-down configurations should be specified by column indices in
range ``(N/2, 0]``. This parameter can be passed as keyword or as the first positional argument.
addresses: (DEPRECATED) An alternative way to specify the configurations, with a length-2 tuple of base-10, unsigned integers such that
caleb-johnson marked this conversation as resolved.
Show resolved Hide resolved
the first element is the set of spin-up configurations and the second element is the
spin-down configurations. For backwards compatibility, this parameter may be passed as the first positional argument during the deprecation period.
hcore: Core Hamiltonian matrix representing single-electron integrals
eri: Electronic repulsion integrals representing two-electron integrals
open_shell: A flag specifying whether configurations from the left and right
halves of the bitstrings should be kept separate. If ``False``, addresses
from the left and right halves of the bitstrings are combined into a single
set of unique configurations and used for both the alpha and beta subspaces.
spin_sq: Target value for the total spin squared for the ground state.
If ``None``, no spin will be imposed.
max_davidson: The maximum number of cycles of Davidson's algorithm
Expand All @@ -76,6 +86,20 @@ def solve_fermion(
Raises:
ValueError: The input determinant ``addresses`` must be non-empty, sorted arrays of integers.
"""
if isinstance(bitstring_matrix, tuple):
warnings.warn(
"Passing a length-2 tuple of sorted addresses to define the subspace is deprecated. Users "
"should instead pass in the bitstring matrix defining the subspace.",
DeprecationWarning,
stacklevel=2,
)
addresses = bitstring_matrix
elif addresses is None:
# This will become the default code path after the deprecation period.
#
# Flip the output so the alpha addresses are on the left with [::-1]
addresses = bitstring_matrix_to_sorted_addresses(bitstring_matrix, open_shell=open_shell)
addresses = addresses[::-1]
addresses = _check_addresses(addresses)

num_up = bin(addresses[0][0])[2:].count("1")
Expand Down Expand Up @@ -108,11 +132,13 @@ def solve_fermion(


def optimize_orbitals(
addresses: tuple[np.ndarray, np.ndarray],
bitstring_matrix: tuple[np.ndarray, np.ndarray] | np.ndarray,
/,
hcore: np.ndarray,
eri: np.ndarray,
k_flat: np.ndarray,
*,
open_shell: bool = False,
spin_sq: float = 0.0,
num_iters: int = 10,
num_steps_grad: int = 10_000,
Expand All @@ -133,20 +159,26 @@ def optimize_orbitals(
Refer to `Sec. II A 4 <https://arxiv.org/pdf/2405.05068>`_ for more detailed
discussion on this orbital optimization technique.

.. note::
The input ``addresses`` are expected to be unique and sorted. While this will be
handled for the user automatically, this function may become slower if the input
addresses are not sorted or nearly-sorted.

Args:
addresses: A length-2 tuple of 1D arrays containing sorted, base-10
representations of bitstrings. The first array represents configurations of the
alpha particles, and the second array represents that of the beta particles.
bitstring_matrix: A set of configurations defining the subspace onto which the Hamiltonian
will be projected and diagonalized. This may be specified with a bitstring matrix -- a
2D array of bool representations of bit values such that each row represents a single
bitstring. The spin-up configurations should be specified by column indices in range
``(N, N/2]``, and the spin-down configurations should be specified by column indices in
range ``(N/2, 0]``.

DEPRECATED: This may also be specified with a length-2 tuple of base-10, unsigned integers such that
the first element is the set of spin-up configurations and the second element is the
spin-down configurations.
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``.
open_shell: A flag specifying whether configurations from the left and right
halves of the bitstrings should be kept separate. If ``False``, addresses
from the left and right halves of the bitstrings are combined into a single
set of unique configurations and used for both the alpha and beta subspaces.
spin_sq: Target value for the total spin squared for the ground state
num_iters: The number of iterations of orbital optimization to perform
max_davidson: The maximum number of cycles of Davidson's algorithm to
Expand All @@ -161,6 +193,18 @@ def optimize_orbitals(
- An optimized 1D array defining the orbital transform
- Average orbital occupancy
"""
if isinstance(bitstring_matrix, tuple):
warnings.warn(
"Passing a length-2 tuple of sorted addresses to define the subspace is deprecated. Users "
"should instead pass in the bitstring matrix defining the subspace.",
DeprecationWarning,
stacklevel=2,
)
addresses = bitstring_matrix
else:
# Flip the output so the alpha addresses are on the left with [::-1]
addresses = bitstring_matrix_to_sorted_addresses(bitstring_matrix, open_shell=open_shell)
addresses = addresses[::-1]
addresses = _check_addresses(addresses)

num_up = bin(addresses[0][0])[2:].count("1")
Expand Down
4 changes: 4 additions & 0 deletions releasenotes/notes/deprecate-addr-526f0c5bf681f739.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
deprecations:
- |
The ``addressess`` positional argument to :func:`qiskit_addon_sqd.fermion.solve_fermion` and :func:`qiskit_addon_sqd.optimize_orbitals` has been deprecated in favor of ``bitstring_matrix``. Users are no longer required to convert their configuration to determinant addresses; instead, they should now pass in the bitstring matrix specifying the subspace onto which to project and diagonalize the Hamiltonian. The conversion to determinant addresses will be done internally.