diff --git a/docs/apidocs/index.rst b/docs/apidocs/index.rst new file mode 100644 index 0000000..a0a6cfd --- /dev/null +++ b/docs/apidocs/index.rst @@ -0,0 +1,12 @@ +********************************** +``qiskit-addon-sqd`` API reference +********************************** + +.. toctree:: + :maxdepth: 1 + + qiskit_addon_sqd.configuration_recovery + qiskit_addon_sqd.counts + qiskit_addon_sqd.fermion + qiskit_addon_sqd.qubit + qiskit_addon_sqd.subsampling diff --git a/docs/apidocs/qiskit_addon_sqd.configuration_recovery.rst b/docs/apidocs/qiskit_addon_sqd.configuration_recovery.rst index 7724266..0b1ecee 100644 --- a/docs/apidocs/qiskit_addon_sqd.configuration_recovery.rst +++ b/docs/apidocs/qiskit_addon_sqd.configuration_recovery.rst @@ -1,10 +1,13 @@ -====================== -Configuration Recovery -====================== - -.. _qiskit_addon_sqd-configuration_recovery: +======================================================================= +Configuration recovery (:mod:`qiskit_addon_sqd.configuration_recovery`) +======================================================================= .. automodule:: qiskit_addon_sqd.configuration_recovery :no-members: :no-inherited-members: :no-special-members: + +.. currentmodule:: qiskit_addon_sqd.configuration_recovery + +.. autofunction:: post_select_by_hamming_weight +.. autofunction:: recover_configurations diff --git a/docs/apidocs/qiskit_addon_sqd.counts.rst b/docs/apidocs/qiskit_addon_sqd.counts.rst index 9d80a54..c47a4b9 100644 --- a/docs/apidocs/qiskit_addon_sqd.counts.rst +++ b/docs/apidocs/qiskit_addon_sqd.counts.rst @@ -1,10 +1,15 @@ -====== -Counts -====== - -.. _qiskit_addon_sqd-counts: +======================================= +Counts (:mod:`qiskit_addon_sqd.counts`) +======================================= .. automodule:: qiskit_addon_sqd.counts :no-members: :no-inherited-members: :no-special-members: + +.. currentmodule:: qiskit_addon_sqd.counts + +.. autofunction:: counts_to_arrays +.. autofunction:: generate_counts_uniform +.. autofunction:: generate_counts_bipartite_hamming +.. autofunction:: normalize_counts_dict diff --git a/docs/apidocs/qiskit_addon_sqd.fermion.rst b/docs/apidocs/qiskit_addon_sqd.fermion.rst index 2470c78..27c7c9e 100644 --- a/docs/apidocs/qiskit_addon_sqd.fermion.rst +++ b/docs/apidocs/qiskit_addon_sqd.fermion.rst @@ -1,10 +1,18 @@ -======= -Fermion -======= - -.. _qiskit_addon_sqd-fermion: +========================================= +Fermion (:mod:`qiskit_addon_sqd.fermion`) +========================================= .. automodule:: qiskit_addon_sqd.fermion :no-members: :no-inherited-members: :no-special-members: + +.. currentmodule:: qiskit_addon_sqd.fermion + +.. autofunction:: bitstring_matrix_to_ci_strs +.. autofunction:: enlarge_batch_from_transitions +.. autofunction:: flip_orbital_occupancies +.. autofunction:: solve_fermion +.. autofunction:: optimize_orbitals +.. autofunction:: rotate_integrals +.. autofunction:: bitstring_matrix_to_sorted_addresses diff --git a/docs/apidocs/qiskit_addon_sqd.qubit.rst b/docs/apidocs/qiskit_addon_sqd.qubit.rst index 7eec7fa..dfd09ef 100644 --- a/docs/apidocs/qiskit_addon_sqd.qubit.rst +++ b/docs/apidocs/qiskit_addon_sqd.qubit.rst @@ -1,10 +1,15 @@ -===== -Qubit -===== - -.. _qiskit_addon_sqd-qubit: +===================================== +Qubit (:mod:`qiskit_addon_sqd.qubit`) +===================================== .. automodule:: qiskit_addon_sqd.qubit :no-members: :no-inherited-members: :no-special-members: + +.. currentmodule:: qiskit_addon_sqd.qubit + +.. autofunction:: solve_qubit +.. autofunction:: project_operator_to_subspace +.. autofunction:: sort_and_remove_duplicates +.. autofunction:: matrix_elements_from_pauli diff --git a/docs/apidocs/qiskit_addon_sqd.rst b/docs/apidocs/qiskit_addon_sqd.rst deleted file mode 100644 index 94e67a0..0000000 --- a/docs/apidocs/qiskit_addon_sqd.rst +++ /dev/null @@ -1,10 +0,0 @@ -==================================== -Sample-based Quantum Diagonalization -==================================== - -.. _qiskit_addon_sqd: - -.. automodule:: qiskit_addon_sqd - :no-members: - :no-inherited-members: - :no-special-members: diff --git a/docs/apidocs/qiskit_addon_sqd.subsampling.rst b/docs/apidocs/qiskit_addon_sqd.subsampling.rst index f043d8a..da7708e 100644 --- a/docs/apidocs/qiskit_addon_sqd.subsampling.rst +++ b/docs/apidocs/qiskit_addon_sqd.subsampling.rst @@ -1,10 +1,13 @@ -=========== -Subsampling -=========== - -.. _qiskit_addon_sqd-subsampling: +================================================= +Subsampling (:mod:`qiskit_addon_sqd.subsampling`) +================================================= .. automodule:: qiskit_addon_sqd.subsampling :no-members: :no-inherited-members: :no-special-members: + +.. currentmodule:: qiskit_addon_sqd.subsampling + +.. autofunction:: subsample +.. autofunction:: postselect_and_subsample diff --git a/docs/conf.py b/docs/conf.py index 90ec773..0854e3f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -59,6 +59,7 @@ "sphinx.ext.intersphinx", "matplotlib.sphinxext.plot_directive", "sphinx_copybutton", + "sphinx_reredirects", "reno.sphinxext", "nbsphinx", "qiskit_sphinx_theme", @@ -107,6 +108,41 @@ plot_working_directory = "." plot_html_show_source_link = False +# ---------------------------------------------------------------------------------- +# Redirects +# ---------------------------------------------------------------------------------- + +_inlined_apis = [ + ("qiskit_addon_sqd.configuration_recovery", "post_select_by_hamming_weight"), + ("qiskit_addon_sqd.configuration_recovery", "recover_configurations"), + ("qiskit_addon_sqd.counts", "counts_to_arrays"), + ("qiskit_addon_sqd.counts", "generate_counts_uniform"), + ("qiskit_addon_sqd.counts", "generate_counts_bipartite_hamming"), + ("qiskit_addon_sqd.counts", "normalize_counts_dict"), + ("qiskit_addon_sqd.fermion", "bitstring_matrix_to_ci_strs"), + ("qiskit_addon_sqd.fermion", "enlarge_batch_from_transitions"), + ("qiskit_addon_sqd.fermion", "flip_orbital_occupancies"), + ("qiskit_addon_sqd.fermion", "solve_fermion"), + ("qiskit_addon_sqd.fermion", "optimize_orbitals"), + ("qiskit_addon_sqd.fermion", "rotate_integrals"), + ("qiskit_addon_sqd.fermion", "bitstring_matrix_to_sorted_addresses"), + ("qiskit_addon_sqd.qubit", "solve_qubit"), + ("qiskit_addon_sqd.qubit", "project_operator_to_subspace"), + ("qiskit_addon_sqd.qubit", "project_operator_to_subspace"), + ("qiskit_addon_sqd.qubit", "sort_and_remove_duplicates"), + ("qiskit_addon_sqd.qubit", "matrix_elements_from_pauli"), + ("qiskit_addon_sqd.subsampling", "subsample"), + ("qiskit_addon_sqd.subsampling", "postselect_and_subsample"), +] + +redirects = { + "apidocs/qiskit_addon_sqd": "./index.html", + **{ + f"stubs/{module}.{name}": f"../apidocs/{module}.html#{module}.{name}" + for module, name in _inlined_apis + }, +} + # ---------------------------------------------------------------------------------- # Source code links # ---------------------------------------------------------------------------------- diff --git a/docs/index.rst b/docs/index.rst index 805d76e..d4dc338 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -97,6 +97,6 @@ References Installation Instructions Tutorials How-To Guides - API Reference + API Reference GitHub Release Notes diff --git a/pyproject.toml b/pyproject.toml index 3871aad..9651efb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,6 @@ style = [ ] lint = [ "qiskit-addon-sqd[style]", - "pydocstyle==6.3.0", "mypy==1.11.2", "pylint==3.3.1", "reno>=4.1", @@ -76,6 +75,7 @@ docs = [ "sphinx-design", "sphinx-autodoc-typehints", "sphinx-copybutton", + "sphinx_reredirects", "nbsphinx>=0.9.4", "reno>=4.1", ] @@ -134,6 +134,7 @@ select = [ "I", # isort "E", # pycodestyle "W", # pycodestyle + "D", # pydocstyle "F", # pyflakes "RUF", # ruff "UP", # pyupgrade @@ -149,8 +150,12 @@ ignore = [ max-args = 6 [tool.ruff.lint.extend-per-file-ignores] +"test/**.py" = [ + "D", # pydocstyle +] "docs/**/*" = [ "E402", # module level import not at top of file + "D", # pydocstyle ] [tool.ruff.lint.flake8-copyright] @@ -167,3 +172,6 @@ notice-rgx = """ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals\\. """ + +[tool.ruff.lint.pydocstyle] +convention = "google" diff --git a/qiskit_addon_sqd/__init__.py b/qiskit_addon_sqd/__init__.py index 46adaa0..e872c06 100644 --- a/qiskit_addon_sqd/__init__.py +++ b/qiskit_addon_sqd/__init__.py @@ -10,23 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -""" -Primary SQD functionality. - -.. currentmodule:: qiskit_addon_sqd - -.. autosummary:: - :toctree: ../stubs/ - :nosignatures: - -Modules -======= -.. autosummary:: - :toctree: - - configuration_recovery - subsampling - counts - fermion - qubit -""" +# Warning: this module is not documented and it does not have an RST file. +# If we ever publicly expose interfaces users can import from this module, +# we should set up its RST file. +"""Primary SQD functionality.""" diff --git a/qiskit_addon_sqd/configuration_recovery.py b/qiskit_addon_sqd/configuration_recovery.py index af97dd3..3d81a55 100644 --- a/qiskit_addon_sqd/configuration_recovery.py +++ b/qiskit_addon_sqd/configuration_recovery.py @@ -10,18 +10,8 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -""" -Functions for performing self-consistent configuration recovery. - -.. currentmodule:: qiskit_addon_sqd.configuration_recovery - -.. autosummary:: - :toctree: ../stubs/ - :nosignatures: - - post_select_by_hamming_weight - recover_configurations -""" +# Reminder: update the RST file in docs/apidocs when adding new interfaces. +"""Functions for performing self-consistent configuration recovery.""" from __future__ import annotations @@ -34,8 +24,7 @@ def post_select_by_hamming_weight( bitstring_matrix: np.ndarray, *, hamming_right: int, hamming_left: int ) -> np.ndarray: - """ - Post-select bitstrings based on the hamming weight of each half. + """Post-select bitstrings based on the hamming weight of each half. Args: bitstring_matrix: A 2D array of ``bool`` representations of bit @@ -45,6 +34,7 @@ def post_select_by_hamming_weight( Returns: A mask signifying which samples (rows) were selected from the input matrix. + """ if hamming_left < 0 or hamming_right < 0: raise ValueError("Hamming weights must be non-negative integers.") @@ -66,8 +56,7 @@ def recover_configurations( num_elec_b: int, rand_seed: int | None = None, ) -> tuple[np.ndarray, np.ndarray]: - """ - Refine bitstrings based on average orbital occupancy and a target hamming weight. + """Refine bitstrings based on average orbital occupancy and a target hamming weight. This function refines each bit in isolation in an attempt to transform the Hilbert space represented by the input ``bitstring_matrix`` into a space closer to that which supports @@ -101,6 +90,7 @@ def recover_configurations( References: [1]: J. Robledo-Moreno, et al., `Chemistry Beyond Exact Solutions on a Quantum-Centric Supercomputer `_, arXiv:2405.05068 [quant-ph]. + """ if num_elec_a < 0 or num_elec_b < 0: raise ValueError("The numbers of electrons must be specified as non-negative integers.") @@ -126,8 +116,7 @@ def recover_configurations( def _p_flip_0_to_1(ratio_exp: float, occ: float, eps: float = 0.01) -> float: # pragma: no cover - """ - Calculate the probability of flipping a bit from 0 to 1. + """Calculate the probability of flipping a bit from 0 to 1. This function will more aggressively flip bits which are in disagreement with the occupation information. @@ -140,6 +129,7 @@ def _p_flip_0_to_1(ratio_exp: float, occ: float, eps: float = 0.01) -> float: # Returns: The probability with which to flip the bit + """ # Occupancy is < than naive expectation. # Flip 0s to 1 with small (~eps) probability in this case @@ -157,8 +147,7 @@ def _p_flip_0_to_1(ratio_exp: float, occ: float, eps: float = 0.01) -> float: # def _p_flip_1_to_0(ratio_exp: float, occ: float, eps: float = 0.01) -> float: # pragma: no cover - """ - Calculate the probability of flipping a bit from 1 to 0. + """Calculate the probability of flipping a bit from 1 to 0. This function will more aggressively flip bits which are in disagreement with the occupation information. @@ -171,6 +160,7 @@ def _p_flip_1_to_0(ratio_exp: float, occ: float, eps: float = 0.01) -> float: # Returns: The probability with which to flip the bit + """ # Occupancy is < naive expectation. # The probability to flip the bit increases linearly from ``eps`` to @@ -195,8 +185,7 @@ def _bipartite_bitstring_correcting( hamming_left: int, rand_seed: int | None = None, ) -> np.ndarray: - """ - Use occupancy information and target hamming weight to correct a bitstring. + """Use occupancy information and target hamming weight to correct a bitstring. Args: bit_array: A 1D array of ``bool`` representations of bit values @@ -207,6 +196,7 @@ def _bipartite_bitstring_correcting( Returns: A corrected bitstring + """ # This function must not mutate the input arrays. bit_array = bit_array.copy() diff --git a/qiskit_addon_sqd/counts.py b/qiskit_addon_sqd/counts.py index 01bd3fa..a996c87 100644 --- a/qiskit_addon_sqd/counts.py +++ b/qiskit_addon_sqd/counts.py @@ -10,20 +10,8 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -""" -Functions for transforming counts dictionaries. - -.. currentmodule:: qiskit_addon_sqd.counts - -.. autosummary:: - :toctree: ../stubs/ - :nosignatures: - - counts_to_arrays - generate_counts_uniform - generate_counts_bipartite_hamming - normalize_counts_dict -""" +# Reminder: update the RST file in docs/apidocs when adding new interfaces. +"""Functions for transforming counts dictionaries.""" from __future__ import annotations @@ -31,8 +19,7 @@ def counts_to_arrays(counts: dict[str, float | int]) -> tuple[np.ndarray, np.ndarray]: - """ - Convert a counts dictionary into a bitstring matrix and a probability array. + """Convert a counts dictionary into a bitstring matrix and a probability array. Args: counts: The counts dictionary to convert @@ -43,6 +30,7 @@ def counts_to_arrays(counts: dict[str, float | int]) -> tuple[np.ndarray, np.nda bitstring, and each element is a ``bool`` representation of the bit's value - A 1D array containing the probability with which each bitstring was sampled + """ if not counts: return np.array([]), np.array([]) @@ -56,8 +44,7 @@ def counts_to_arrays(counts: dict[str, float | int]) -> tuple[np.ndarray, np.nda def generate_counts_uniform( num_samples: int, num_bits: int, rand_seed: None | int = None ) -> dict[str, int]: - """ - Generate a bitstring counts dictionary of samples drawn from the uniform distribution. + """Generate a bitstring counts dictionary of samples drawn from the uniform distribution. Args: num_samples: The number of samples to draw @@ -70,6 +57,7 @@ def generate_counts_uniform( Raises: ValueError: ``num_samples`` and ``num_bits`` must be positive integers. + """ if num_samples < 1: raise ValueError("The number of samples must be specified with a positive integer.") @@ -96,8 +84,7 @@ def generate_counts_bipartite_hamming( hamming_left: int, rand_seed: None | int = None, ) -> dict[str, int]: - """ - Generate a bitstring counts dictionary with specified bipartite hamming weight. + """Generate a bitstring counts dictionary with specified bipartite hamming weight. Args: num_samples: The number of samples to draw @@ -115,6 +102,7 @@ def generate_counts_bipartite_hamming( ValueError: ``num_bits`` and ``num_samples`` must be positive integers. ValueError: Hamming weights must be specified as non-negative integers. ValueError: ``num_bits`` must be even. + """ if num_bits % 2 != 0: raise ValueError("The number of bits must be specified with an even integer.") diff --git a/qiskit_addon_sqd/fermion.py b/qiskit_addon_sqd/fermion.py index 52a373d..c90794d 100644 --- a/qiskit_addon_sqd/fermion.py +++ b/qiskit_addon_sqd/fermion.py @@ -10,23 +10,8 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -""" -Functions for the study of fermionic systems. - -.. currentmodule:: qiskit_addon_sqd.fermion - -.. autosummary:: - :toctree: ../stubs/ - :nosignatures: - - bitstring_matrix_to_ci_strs - enlarge_batch_from_transitions - flip_orbital_occupancies - solve_fermion - optimize_orbitals - rotate_integrals - bitstring_matrix_to_sorted_addresses -""" +# Reminder: update the RST file in docs/apidocs when adding new interfaces. +"""Functions for the study of fermionic systems.""" from __future__ import annotations @@ -115,6 +100,7 @@ def solve_fermion( - The SCI ground state - Average occupancy of the alpha and beta orbitals, respectively - Expectation value of spin-squared + """ if isinstance(bitstring_matrix, tuple): warnings.warn( @@ -173,8 +159,7 @@ def optimize_orbitals( learning_rate: float = 0.01, max_davidson: int = 100, ) -> tuple[float, np.ndarray, list[np.ndarray]]: - """ - Optimize orbitals to produce a minimal ground state. + """Optimize orbitals to produce a minimal ground state. The process involves iterating over 3 steps: @@ -220,6 +205,7 @@ def optimize_orbitals( - The groundstate energy found during the last optimization iteration - An optimized 1D array defining the orbital transform - Average orbital occupancy + """ if isinstance(bitstring_matrix, tuple): warnings.warn( @@ -276,8 +262,7 @@ def optimize_orbitals( def rotate_integrals( hcore: np.ndarray, eri: np.ndarray, k_flat: np.ndarray ) -> tuple[np.ndarray, np.ndarray]: - r""" - Perform a similarity transform on the integrals. + r"""Perform a similarity transform on the integrals. The transformation is described as: @@ -297,6 +282,7 @@ def rotate_integrals( Returns: - The rotated core Hamiltonian matrix - The rotated ERI matrix + """ num_orbitals = hcore.shape[0] p = np.reshape(k_flat, (num_orbitals, num_orbitals)) @@ -309,8 +295,7 @@ def rotate_integrals( def flip_orbital_occupancies(occupancies: np.ndarray) -> np.ndarray: - """ - Flip an orbital occupancy array to match the indexing of a bitstring. + """Flip an orbital occupancy array to match the indexing of a bitstring. This function reformats a 1D array of spin-orbital occupancies formatted like: @@ -341,8 +326,7 @@ def flip_orbital_occupancies(occupancies: np.ndarray) -> np.ndarray: def bitstring_matrix_to_sorted_addresses( bitstring_matrix: np.ndarray, open_shell: bool = False ) -> tuple[np.ndarray, np.ndarray]: - """ - Convert a bitstring matrix into a sorted array of unique, unsigned integers. + """Convert a bitstring matrix into a sorted array of unique, unsigned integers. This function separates each bitstring in ``bitstring_matrix`` in half, flips the bits and translates them into integer representations, and finally appends them to @@ -361,6 +345,7 @@ def bitstring_matrix_to_sorted_addresses( Returns: A length-2 tuple of sorted, unique determinants 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] @@ -388,8 +373,7 @@ def bitstring_matrix_to_sorted_addresses( 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 integer representations of determinants. + """Convert bitstrings (rows) in a ``bitstring_matrix`` into integer representations of determinants. This function separates each bitstring in ``bitstring_matrix`` in half, flips the bits and translates them into integer representations, and finally appends them to @@ -408,6 +392,7 @@ def bitstring_matrix_to_ci_strs( Returns: A length-2 tuple of determinant lists 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] @@ -435,8 +420,7 @@ def bitstring_matrix_to_ci_strs( def enlarge_batch_from_transitions( bitstring_matrix: np.ndarray, transition_operators: np.ndarray ) -> np.ndarray: - """ - Apply the set of transition operators to the configurations represented in ``bitstring_matrix``. + """Apply the set of transition operators to the configurations represented in ``bitstring_matrix``. Args: bitstring_matrix: A 2D array of ``bool`` representations of bit @@ -448,6 +432,7 @@ def enlarge_batch_from_transitions( Returns: Bitstring matrix representing the augmented set of electronic configurations after applying the excitation operators. + """ diag, create, annihilate = _transition_str_to_bool(transition_operators) @@ -493,8 +478,7 @@ def _optimize_orbitals_sci( hcore: np.ndarray, eri: np.ndarray, ) -> None: - """ - Optimize orbital rotation parameters in-place using gradient descent. + """Optimize orbital rotation parameters in-place using gradient descent. This procedure is described in `Sec. II A 4 `_. """ @@ -514,8 +498,7 @@ def _SCISCF_Energy_contract( num_orbitals: int, k_flat: np.ndarray, ) -> Array: - """ - Calculate gradient. + """Calculate gradient. The gradient can be calculated by contracting the bare one and two-body reduced density matrices with the gradients of the of the one and two-body @@ -554,8 +537,7 @@ def _apply_excitation_single( def _transition_str_to_bool(string_rep: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]: - """ - Transform string representations of a transition operator into bool representation. + """Transform string representations of a transition operator into bool representation. Transform sequences of identity ("I"), creation ("+"), annihilation ("-"), and number ("n") characters into the internal representation used to apply the transitions into electronic @@ -570,6 +552,7 @@ def _transition_str_to_bool(string_rep: np.ndarray) -> tuple[np.ndarray, np.ndar - A mask signifying the diagonal terms (I). - A mask signifying whether there is a creation operator (+). - A mask signifying whether there is an annihilation operator (-). + """ diag = np.logical_or(string_rep == "I", string_rep == "n") create = np.logical_or(string_rep == "+", string_rep == "n") diff --git a/qiskit_addon_sqd/qubit.py b/qiskit_addon_sqd/qubit.py index aa7c7bc..54ad6e9 100644 --- a/qiskit_addon_sqd/qubit.py +++ b/qiskit_addon_sqd/qubit.py @@ -10,21 +10,8 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -""" -Functions for handling quantum samples. - -.. currentmodule:: qiskit_addon_sqd.qubit - -.. autosummary:: - :toctree: ../stubs/ - :nosignatures: - - solve_qubit - project_operator_to_subspace - sort_and_remove_duplicates - matrix_elements_from_pauli - sort_and_remove_duplicates -""" +# Reminder: update the RST file in docs/apidocs when adding new interfaces. +"""Functions for handling quantum samples.""" from typing import Any @@ -46,8 +33,7 @@ def solve_qubit( verbose: bool = False, **scipy_kwargs, ) -> tuple[np.ndarray, np.ndarray]: - """ - Find the energies and eigenstates of a Hamiltonian projected into a subspace. + """Find the energies and eigenstates of a Hamiltonian projected into a subspace. The subspace is defined by a collection of computational basis states which are specified by the bitstrings (rows) in the ``bitstring_matrix``. @@ -69,6 +55,7 @@ def solve_qubit( Raises: ValueError: Bitstrings (rows) in ``bitstring_matrix`` must have length < ``64``. + """ if bitstring_matrix.shape[1] > 63: raise ValueError("Bitstrings (rows) in bitstring_matrix must have length < 64.") @@ -93,8 +80,7 @@ def project_operator_to_subspace( *, verbose: bool = False, ) -> spmatrix: - """ - Project a Pauli operator onto a Hilbert subspace defined by the computational basis states (rows) in ``bitstring_matrix``. + """Project a Pauli operator onto a Hilbert subspace defined by the computational basis states (rows) in ``bitstring_matrix``. The output sparse matrix, ``A``, represents an ``NxN`` matrix s.t. ``N`` is the number of rows in ``bitstring_matrix``. The rows of ``A`` represent the input configurations, and the columns @@ -129,6 +115,7 @@ def project_operator_to_subspace( Raises: ValueError: Bitstrings (rows) in ``bitstring_matrix`` must have length < ``64``. + """ if bitstring_matrix.shape[1] > 63: raise ValueError("Bitstrings (rows) in bitstring_matrix must have length < 64.") @@ -157,8 +144,7 @@ def project_operator_to_subspace( def sort_and_remove_duplicates(bitstring_matrix: np.ndarray) -> np.ndarray: - """ - Sort a bitstring matrix and remove duplicate entries. + """Sort a bitstring matrix and remove duplicate entries. The lowest bitstring values will be placed in the lowest-indexed rows. @@ -168,6 +154,7 @@ def sort_and_remove_duplicates(bitstring_matrix: np.ndarray) -> np.ndarray: Returns: Sorted version of ``bitstring_matrix`` without repeated rows. + """ bsmat_asints = _int_conversion_from_bts_matrix_vmap(bitstring_matrix) @@ -179,8 +166,7 @@ def sort_and_remove_duplicates(bitstring_matrix: np.ndarray) -> np.ndarray: def matrix_elements_from_pauli( bitstring_matrix: np.ndarray, pauli: Pauli ) -> tuple[np.ndarray, np.ndarray, np.ndarray]: - """ - Find the sparse matrix elements of a Pauli operator in the subspace defined by the bitstrings. + """Find the sparse matrix elements of a Pauli operator in the subspace defined by the bitstrings. The sparse matrix, ``A``, defined by the outputs represents an ``NxN`` matrix s.t. ``N`` is the number of rows in ``bitstring_matrix``. The rows of ``A`` represent the input configurations, and the columns @@ -215,6 +201,7 @@ def matrix_elements_from_pauli( Raises: ValueError: Bitstrings (rows) in ``bitstring_matrix`` must have length < ``64``. + """ if bitstring_matrix.shape[1] > 63: raise ValueError("Bitstrings (rows) in bitstring_matrix must have length < 64.") @@ -255,10 +242,10 @@ def matrix_elements_from_pauli( def _connected_elements_and_amplitudes_bool( bitstring_matrix: np.ndarray, diag: np.ndarray, sign: np.ndarray, imag: np.ndarray ) -> tuple[NDArray[np.bool_], Array]: - """ - Find the connected element to computational basis state |X>. + """Find the connected element to computational basis state |X>. Given a Pauli operator represented by ``{diag, sign, imag}``. + Args: bitstring_matrix: A 1D array of ``bool`` representations of bits. diag: ``bool`` whether the Pauli operator is diagonal. Only ``True`` @@ -271,6 +258,7 @@ def _connected_elements_and_amplitudes_bool( Returns: A matrix of bitstrings where each row is the connected element to the input the matrix element. + """ bitstring_matrix_mask: NDArray[np.bool_] = bitstring_matrix == diag return bitstring_matrix_mask, jnp.prod( @@ -289,8 +277,7 @@ def _connected_elements_and_amplitudes_bool( def _int_conversion_from_bts_array(bit_array: np.ndarray) -> Any: - """ - Convert a bit array to an integer representation. + """Convert a bit array to an integer representation. NOTE: This can only handle up to 63 qubits. Then the integer will overflow @@ -299,6 +286,7 @@ def _int_conversion_from_bts_array(bit_array: np.ndarray) -> Any: Returns: Integer representation of the bit array. + """ n_qubits = len(bit_array) bitarray_asint = 0.0 diff --git a/qiskit_addon_sqd/subsampling.py b/qiskit_addon_sqd/subsampling.py index ec504ac..d603768 100644 --- a/qiskit_addon_sqd/subsampling.py +++ b/qiskit_addon_sqd/subsampling.py @@ -10,18 +10,8 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -""" -Functions for creating batches of samples from a bitstring matrix. - -.. currentmodule:: qiskit_addon_sqd.subsampling - -.. autosummary:: - :toctree: ../stubs/ - :nosignatures: - - subsample - postselect_and_subsample -""" +# Reminder: update the RST file in docs/apidocs when adding new interfaces. +"""Functions for creating batches of samples from a bitstring matrix.""" from __future__ import annotations @@ -40,8 +30,7 @@ def postselect_and_subsample( num_batches: int, rand_seed: int | None = None, ) -> list[np.ndarray]: - """ - Subsample batches of bit arrays with correct hamming weight from an input ``bitstring_matrix``. + """Subsample batches of bit arrays with correct hamming weight from an input ``bitstring_matrix``. Bitstring samples with incorrect hamming weight on either their left or right half will not be sampled. @@ -67,6 +56,7 @@ def postselect_and_subsample( ValueError: The number of elements in ``probabilities`` must equal the number of rows in ``bitstring_matrix``. ValueError: Hamming weights must be non-negative integers. ValueError: Samples per batch and number of batches must be positive integers. + """ num_bitstrings = len(bitstring_matrix) if num_bitstrings == 0: @@ -99,8 +89,7 @@ def subsample( num_batches: int, rand_seed: int | None = None, ) -> list[np.ndarray]: - """ - Subsample batches of bit arrays from an input ``bitstring_matrix``. + """Subsample batches of bit arrays from an input ``bitstring_matrix``. Each individual batch will be sampled without replacement from the input ``bitstring_matrix``. Samples will be replaced after creation of each batch, so different batches may contain @@ -120,6 +109,7 @@ def subsample( Raises: ValueError: The number of elements in ``probabilities`` must equal the number of rows in ``bitstring_matrix``. ValueError: Samples per batch and number of batches must be positive integers. + """ if bitstring_matrix.shape[0] < 1: return [np.array([])] * num_batches diff --git a/tox.ini b/tox.ini index 810024a..5a890cf 100644 --- a/tox.ini +++ b/tox.ini @@ -29,7 +29,6 @@ commands = ruff check qiskit_addon_sqd/ docs/ test/ ruff check --preview --select CPY001 --exclude "*.ipynb" qiskit_addon_sqd/ test/ nbqa ruff docs/ - pydocstyle qiskit_addon_sqd/ mypy qiskit_addon_sqd/ pylint -rn qiskit_addon_sqd/ test/ nbqa pylint -rn docs/