-
Notifications
You must be signed in to change notification settings - Fork 12
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
Remove discussion of addresses from API and docs and replace with "CI strings" #54
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,12 +19,13 @@ | |
:toctree: ../stubs/ | ||
:nosignatures: | ||
|
||
bitstring_matrix_to_sorted_addresses | ||
bitstring_matrix_to_ci_strs | ||
enlarge_batch_from_transitions | ||
flip_orbital_occupancies | ||
solve_fermion | ||
optimize_orbitals | ||
rotate_integrals | ||
bitstring_matrix_to_sorted_addresses | ||
""" | ||
|
||
from __future__ import annotations | ||
|
@@ -36,6 +37,7 @@ | |
from jax import numpy as jnp | ||
from jax.scipy.linalg import expm | ||
from pyscf import fci | ||
from qiskit.utils import deprecate_func | ||
from scipy import linalg as LA | ||
|
||
config.update("jax_enable_x64", True) # To deal with large integers | ||
|
@@ -69,7 +71,7 @@ def solve_fermion( | |
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 | ||
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 | ||
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. | ||
|
@@ -83,25 +85,22 @@ def solve_fermion( | |
- SCI coefficients | ||
- Average orbital occupancy | ||
- Expectation value of spin-squared | ||
|
||
Raises: | ||
ValueError: The input determinant ``addresses`` must be non-empty, sorted arrays of integers. | ||
""" | ||
if isinstance(bitstring_matrix, tuple): | ||
warnings.warn( | ||
"Passing the input determinants as integers is deprecated. Users should instead pass a bitstring matrix defining the subspace.", | ||
DeprecationWarning, | ||
stacklevel=2, | ||
) | ||
addresses = bitstring_matrix | ||
ci_strs = bitstring_matrix | ||
else: | ||
# This will become the default code path after the deprecation period. | ||
addresses = bitstring_matrix_to_sorted_addresses(bitstring_matrix, open_shell=open_shell) | ||
addresses = addresses[::-1] | ||
addresses = _check_addresses(addresses) | ||
ci_strs = bitstring_matrix_to_ci_strs(bitstring_matrix, open_shell=open_shell) | ||
ci_strs = ci_strs[::-1] | ||
ci_strs = _check_ci_strs(ci_strs) | ||
|
||
num_up = format(addresses[0][0], "b").count("1") | ||
num_dn = format(addresses[1][0], "b").count("1") | ||
num_up = format(ci_strs[0][0], "b").count("1") | ||
num_dn = format(ci_strs[1][0], "b").count("1") | ||
|
||
# Number of molecular orbitals | ||
norb = hcore.shape[0] | ||
|
@@ -115,7 +114,7 @@ def solve_fermion( | |
eri, | ||
norb, | ||
(num_up, num_dn), | ||
ci_strs=addresses, | ||
ci_strs=ci_strs, | ||
verbose=verbose, | ||
max_cycle=max_davidson, | ||
) | ||
|
@@ -174,7 +173,7 @@ def optimize_orbitals( | |
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 | ||
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 | ||
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 | ||
|
@@ -193,20 +192,20 @@ def optimize_orbitals( | |
""" | ||
if isinstance(bitstring_matrix, tuple): | ||
warnings.warn( | ||
"Passing a length-2 tuple of sorted addresses to define the subspace is deprecated. Users " | ||
"Passing a length-2 tuple of base-10 determinants to define the subspace is deprecated. Users " | ||
"should instead pass in the bitstring matrix defining the subspace.", | ||
DeprecationWarning, | ||
stacklevel=2, | ||
) | ||
addresses = bitstring_matrix | ||
ci_strs = 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) | ||
# Flip the output so the alpha CI strs are on the left with [::-1] | ||
ci_strs = bitstring_matrix_to_ci_strs(bitstring_matrix, open_shell=open_shell) | ||
ci_strs = ci_strs[::-1] | ||
ci_strs = _check_ci_strs(ci_strs) | ||
|
||
num_up = format(addresses[0][0], "b").count("1") | ||
num_dn = format(addresses[1][0], "b").count("1") | ||
num_up = format(ci_strs[0][0], "b").count("1") | ||
num_dn = format(ci_strs[1][0], "b").count("1") | ||
|
||
# TODO: Need metadata showing the optimization history | ||
## hcore and eri in physicist ordering | ||
|
@@ -227,7 +226,7 @@ def optimize_orbitals( | |
eri_rot_chem, | ||
num_orbitals, | ||
(num_up, num_dn), | ||
ci_strs=addresses, | ||
ci_strs=ci_strs, | ||
max_cycle=max_davidson, | ||
) | ||
|
||
|
@@ -303,6 +302,12 @@ def flip_orbital_occupancies(occupancies: np.ndarray) -> np.ndarray: | |
return occ_out | ||
|
||
|
||
@deprecate_func( | ||
removal_timeline="no sooner than qiskit-addon-sqd 0.8.0", | ||
since="0.6.0", | ||
package_name="qiskit-addon-sqd", | ||
additional_msg="Use the bitstring_matrix_to_ci_strs function.", | ||
) | ||
def bitstring_matrix_to_sorted_addresses( | ||
bitstring_matrix: np.ndarray, open_shell: bool = False | ||
) -> tuple[np.ndarray, np.ndarray]: | ||
|
@@ -324,8 +329,8 @@ def bitstring_matrix_to_sorted_addresses( | |
and right bitstrings. | ||
|
||
Returns: | ||
A length-2 tuple of sorted, unique base-10 determinant addresses representing the left | ||
and right halves of the bitstrings, respectively. | ||
A length-2 tuple of sorted, unique base-10 determinant addresses representing the | ||
left (spin-down) and right (spin-up) halves of the bitstrings, respectively. | ||
""" | ||
num_orbitals = bitstring_matrix.shape[1] // 2 | ||
num_configs = bitstring_matrix.shape[0] | ||
|
@@ -350,6 +355,53 @@ def bitstring_matrix_to_sorted_addresses( | |
return addresses_left, addresses_right | ||
|
||
|
||
def bitstring_matrix_to_ci_strs( | ||
bitstring_matrix: np.ndarray, open_shell: bool = False | ||
) -> tuple[np.ndarray, np.ndarray]: | ||
""" | ||
Convert bitstrings (rows) in a ``bitstring_matrix`` into base-10 integer representations of determinants. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They're just integers, not "base-10" integers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I started thinking that integers can be specified as base-2, which is a pretty natural way to specify these configurations as well. So I thought being explicit wouldn't hurt. I guess saying "integer" in a software context implies base-10 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The integers can be specified in base-2, or any other base. That's my point. The base 10 is not special here, nor in a general software context. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed all base-10 mentions in fermion module There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, on further thought, base 2 is special here, because the integer representation of a determinant is obtained by converting its string representation to an integer, in base 2. |
||
|
||
This function separates each bitstring in ``bitstring_matrix`` in half, flips the | ||
bits and translates them into integer representations, and finally appends them to | ||
their respective (spin-up or spin-down) lists. Those lists are sorted and output | ||
from this function. | ||
|
||
Args: | ||
bitstring_matrix: A 2D array of ``bool`` representations of bit | ||
values such that each row represents a single bitstring | ||
open_shell: A flag specifying whether unique configurations from the left and right | ||
halves of the bitstrings should be kept separate. If ``False``, configurations | ||
from the left and right halves of the bitstrings are combined into a single | ||
set of unique configurations. That combined set will be returned for both the left | ||
and right bitstrings. | ||
|
||
Returns: | ||
A length-2 tuple of sorted, unique base-10 determinants representing the | ||
right (spin-up) and left (spin-down) halves of the bitstrings, respectively. | ||
""" | ||
num_orbitals = 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:] | ||
|
||
# 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) | ||
|
||
ci_strs_right = np.unique(ci_str_right.astype("longlong")) | ||
ci_strs_left = np.unique(ci_str_left.astype("longlong")) | ||
|
||
if not open_shell: | ||
ci_strs_left = ci_strs_right = np.union1d(ci_strs_left, ci_strs_right) | ||
|
||
return ci_strs_right, ci_strs_left | ||
|
||
|
||
def enlarge_batch_from_transitions( | ||
bitstring_matrix: np.ndarray, transition_operators: np.ndarray | ||
) -> np.ndarray: | ||
|
@@ -376,25 +428,25 @@ def enlarge_batch_from_transitions( | |
return np.array(bitstring_matrix_augmented) | ||
|
||
|
||
def _check_addresses( | ||
addresses: tuple[np.ndarray, np.ndarray], | ||
def _check_ci_strs( | ||
ci_strs: tuple[np.ndarray, np.ndarray], | ||
) -> tuple[np.ndarray, np.ndarray]: | ||
"""Make sure the hamming weight is consistent in all determinants.""" | ||
addr_up, addr_dn = addresses | ||
addr_up, addr_dn = ci_strs | ||
addr_up_ham = format(addr_up[0], "b").count("1") | ||
for i, addr in enumerate(addr_up): | ||
ham = format(addr, "b").count("1") | ||
if ham != addr_up_ham: | ||
raise ValueError( | ||
f"Spin-up address in index 0 has hamming weight {addr_up_ham}, but address in " | ||
f"Spin-up CI string in index 0 has hamming weight {addr_up_ham}, but CI string in " | ||
f"index {i} has hamming weight {ham}." | ||
) | ||
addr_dn_ham = format(addr_dn[0], "b").count("1") | ||
for i, addr in enumerate(addr_dn): | ||
ham = format(addr, "b").count("1") | ||
if ham != addr_dn_ham: | ||
raise ValueError( | ||
f"Spin-down address in index 0 has hamming weight {addr_dn_ham}, but address in " | ||
f"Spin-down CI string in index 0 has hamming weight {addr_dn_ham}, but CI string in " | ||
f"index {i} has hamming weight {ham}." | ||
) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think simply "determinants" is more accurate than "base-10 determinants." They are simply integers, without reference to a "base."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the warning message