hqs_distiller.utils

Utility functions for the HQS Distiller package.

@private

Copyright © 2022-2025 HQS Quantum Simulations GmbH. All Rights Reserved.

def get_random_state_for_operator( batch_size: int, state_shape: tuple[int, int], dtype: numpy.dtype) -> numpy.ndarray:

Initialize random state.

Arguments:
  • batch_size (int): Size of batch of random states.
  • state_shape (tuple[int, int]): Shape of a single state.
  • dtype (xp.datype): Data type of state.
Returns:

xp.ndarray: Normalized random state.

def sgn_p(x: numpy.ndarray) -> numpy.ndarray:

Sign function using convention sgn(0) = 1.

Arguments:
  • x (np.ndarray): numpy array of floats.
Returns:

np.ndarray: numpy array of sign of x.

def sgn_n(x: numpy.ndarray) -> numpy.ndarray:

Sign function using convention sgn(0) = -1.

Arguments:
  • x (np.ndarray): numpy array of floats.
Returns:

np.ndarray: numpy array of sign of x.

def get_integration_contour( window: tuple[float, float], num: int = 4, contour_type: str = 'full_circle') -> tuple[numpy.ndarray, numpy.ndarray]:

Returns integration contour from energy window.

Arguments:
  • window (tuple[float, float]): Spectral window
  • num (int): Number of integration points per semi-circle. Defaults to 4.
  • contour_type (str): Specify type of integration contour. Currently supported: 'full_circle', 'upper_semi_circle', 'lower_semi_circle'. Defaults to 'full_circle'.
Returns:

tuple[np.ndarray, np.ndarray]: tuple (z, dz). z is an array containing the (complex) integration points. dz is an array containing the (complex) integration weights.

Raises:
  • ValueError: If 'contour_type' argument is not supported.
def diagonalize_subspace( matrix: scipy.sparse._matrix.spmatrix, basis: numpy.ndarray, svd_cutoff: float) -> tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]:

Diagonalize subspace spanned by trial states.

Arguments:
  • matrix (SPM.spmatrix): Matrix to diagonalize.
  • basis (np.ndarray): Trial states.
  • svd_cutoff (float): Cut-off criterion for svd.
Returns:

tuple[np.ndarray, np.ndarray, np.ndarray]: tuple of convergence flag, eigenvalues and eigenvectors.

def diagonalize_subspace_operator( hamiltonian_operator: Callable[[numpy.ndarray, numpy.ndarray], numpy.ndarray], subspace: list[hqs_distiller.state_io.State], svd_cutoff: float, verbose: bool) -> tuple[numpy.ndarray, numpy.ndarray, list[hqs_distiller.state_io.State]]:

Diagonalize subspace spanned by trial states.

Arguments:
  • hamiltonian_operator (Callable[[xp.ndarray, xp.ndarray], xp.ndarray]): Operator to diagonalize.
  • subspace (list[State]): States spanning subspace to diagonalize.
  • svd_cutoff (float): Cutoff criterion for svd.
  • verbose (bool): If True, print information.
Returns:

tuple[np.ndarray, np.ndarray, list[State]]: tuple of convergence flag, eigenvalues and eigenstates.

def diagonalize_subspace_operator_batched( hamiltonian_operator: Callable[[numpy.ndarray, numpy.ndarray], numpy.ndarray], subspace: list[hqs_distiller.state_io.StateBatch], svd_cutoff: float, verbose: bool) -> tuple[numpy.ndarray, numpy.ndarray, list[hqs_distiller.state_io.StateBatch]]:

Diagonalize subspace spanned by trial states.

Arguments:
  • hamiltonian_operator (Callable[[xp.ndarray, xp.ndarray], xp.ndarray]): Operator to diagonalize.
  • subspace (list[State]): States spanning subspace to diagonalize.
  • svd_cutoff (float): Cutoff criterion for svd.
  • verbose (bool): If True, print information.
Returns:

tuple[np.ndarray, np.ndarray, list[StateBatch]]: tuple of convergence flag, eigenvalues and eigenstates.

def get_number_of_chebyshev_moments( window: tuple[float, float], bounds: tuple[float, float], n_states: int, n_max_chebyshev_moments: int = 65536, n_min_chebyshev_moments: int = 16) -> int:

Get number of Chebyshev moments from simple heuristic.

Determines the number of Chebyshev moments to resolve a given spectral window. The number of moments is determined by the ratio of the full width of the spectrum to the spectral window augemented by a heuristic scaling factor n_states, which can be the number of states in the spectral window (as suggested by the name).

Arguments:
  • window (tuple[float, float]): Spectral window to resolve.
  • bounds (tuple[float, float]): Spectral bounds.
  • n_states (int): Estimate for number of states in window.
  • n_max_chebyshev_moments (int): Maximal number of Chebyshev moments. Defaults to MAX_CHEBYSHEV_MOMENTS.
  • n_min_chebyshev_moments (int): Minimal number of Chebyshev moments. Defaults to MIN_CHEBYSHEV_MOMENTS.
Returns:

int: Suggested number of Chebyshev moments.

def get_scale_from_windows( window: tuple[float, float], chebyshev_window: tuple[float, float]) -> float:

Get scale from ratio equivalent energy window.

The scale between two energy window is determined.

NOTE: It is assumed that the two given windows refer two equivalent intervals. A global shift in any of the two intervals does not matter.

Arguments:
  • window (tuple[float, float]): Reference energy window.
  • chebyshev_window (tuple[float, float]): Scaled energy window.
Returns:

float: scale = chebyshev_window / window

def get_shift_from_windows( window: tuple[float, float], chebyshev_window: tuple[float, float]) -> float:

Get shift from two equivalent energy window.

The shift between two energy window is determined.

NOTE: It is assumed that the two given windows refer two equivalent intervals. The shift between the intervals is determined by first finding the scale factor between the intervals and then extracting the shift that renders them equivalent.

Arguments:
  • window (tuple[float, float]): Reference energy window.
  • chebyshev_window (tuple[float, float]): Scaled and shifted energy window.
Returns:

float: scale = chebyshev_window / window

def get_integration_grid_from_window( window: tuple[float, float], n_grid_points: int = 100) -> tuple[numpy.ndarray, float]:

Generate integration grid from window.

NOTE: Numpy's linspace is used to generate the grid, but shifted by a "half-interval" to avoid the boundaries if the interval.

Arguments:
  • window (tuple[float, float]): Tuple of lower and upper bound of interval.
  • n_grid_points (int): Number of grid points. Defaults to 100.
Returns:

tuple[np.ndarray, float]: Tuple of integration grid and weight.

def integration_analyzer( w: numpy.ndarray, i_dos: numpy.ndarray, n_states_limit: int) -> tuple[list[float], int]:

Return list of sub-intervals.

The sub-intervals are determined by the requirement, that the density of states (DOS) in each sub-interval integrates at most to the specified limit

Arguments:
  • w (np.ndarray): energy window.
  • i_dos (np.ndarray): integrated DOS of energy window.
  • n_states_limit (int): Maximal number of states in sub-interval.
Returns:

list[tuple[float, float]]: List of sub-intervals. float: Estimate number of states in each subinterval.

def split_states( window: tuple[float, float], converged: numpy.ndarray, e0: numpy.ndarray, r0: numpy.ndarray) -> tuple[tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray], tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]]:

Splits a set of eigenstates given an energy window.

Splits the set of eigenstates into eigenstates within the given energy window and eigenstates outside the given window.

Arguments:
  • window (tuple[float, float]): Energy window.
  • converged (np.ndarray): Convergence flag.
  • e0 (np.ndarray): Eigenvalues.
  • r0 (np.ndarray): Eigenstates.
Returns:

tuple[tuple[np.ndarray, np.ndarray, np.ndarray]: Tuple of merged convergence flags, merged eigenvalues, merged eigenstates.

def merge_chebyshev_moments( chebyshev_moments_a: numpy.ndarray, chebyshev_moments_b: numpy.ndarray) -> numpy.ndarray:

Merge two sets of chebyshev moments.

The sets are expected to be arrays of shape (n_cheby, n_samples) and are concatenated along the second dimension (samples). When the order of chebyshev moments is different in both sets, the missing (higher order) moments are taken to be zero.

Arguments:
  • chebyshev_moments_a (np.ndarray): First set of Chebyshev moments.
  • chebyshev_moments_b (np.ndarray): Second set of Chebyshev moments.
Returns:

np.ndarray: Set of Chebyshev moments.

def get_random_filename() -> str:

Generate random filename.

Uses the uuid4 function of the uuid module to generate a random filename consisting of 32 (hexa-decimal) characters, i.e., a string composed of lower case characters 'a', 'b', 'c', 'd', 'e', and 'f' and numbers '0', '1', ..., '9'.

Returns:

str: Random filename.

def plot_density_of_states( fname: str, w: numpy.ndarray, dos: numpy.ndarray, intervals: Optional[list[tuple[float, float]]] = None, energies: Optional[list[float]] = None, title: str = 'density of states') -> None:

Generate DOS plot and store in svg file.

Arguments:
  • fname (str): Filename for output file.
  • w (np.ndarray): Discretized energy window (grid points).
  • dos (np.ndarray): DOS on energy grid points.
  • intervals (list[tuple[float, float]]): List of intervals to be highlighted in the plot. Defaults to [].
  • energies (list[float]): List of energy values to be highlighted. Defaults to [].
  • title (str): Title for the plot. Defaults to "density of states".
def plot_k_dependent_density_of_states( fname: str, w: numpy.ndarray, dos: numpy.ndarray, special_points_map: dict[int, str], title: str = 'k-point resolved density of states') -> None:

Generate k-resolved DOS heatmap and store in svg file.

Arguments:
  • fname (str): Filename for output file.
  • w (np.ndarray): Discretized energy window (grid points).
  • dos (np.ndarray): DOS on energy grid points.
  • special_points_map (dict[int, str]): Map from k-point indices to labels.
  • title (str): Title for the plot. Defaults to "density of states".