Source code for qDNA.hamiltonian.ham_analysis

from itertools import product

import numpy as np

__all__ = [
    "calc_average_pop",
    "calc_amplitudes",
    "calc_frequencies",
    "get_pop_fourier",
    "calc_ipr_hamiltonian",
]

# ----------------------------------------------------------------------


[docs] def calc_average_pop(eigs, init_state, end_state): """Calculates the time-averaged/ static population of the end state when initially in the initial state. Parameters ---------- eigs : np.ndarray Eigenvector matrix. init_state : int Initial state in the basis. end_state : int End state in the basis. Returns ------- float The static population of the end state. """ average_pop = np.sum(eigs[end_state, :] ** 2 * eigs[init_state, :] ** 2) return average_pop
[docs] def calc_amplitudes(eigs, init_state, end_state): """Calculates the amplitudes for transitions between states. Parameters ---------- eigs : np.ndarray Eigenvector matrix. init_state : int Initial state in the basis. end_state : int End state in the basis. Returns ------- np.ndarray A list of amplitudes for transitions. """ matrix_dimension = eigs.shape[0] amplitudes = [ 2 * eigs[end_state, i] * eigs[init_state, i] * eigs[end_state, j] * eigs[init_state, j] for i, j in product(range(matrix_dimension), repeat=2) if i < j ] return np.real(np.array(amplitudes))
[docs] def calc_frequencies(eigv): """Calculates the frequencies corresponding to energy level differences. Parameters ---------- eigv : np.ndarray Eigenvalue vector. Returns ------- np.ndarray A list of frequencies. """ matrix_dimension = len(eigv) frequencies = [ abs(eigv[i] - eigv[j]).real for i, j in product(range(matrix_dimension), repeat=2) if i < j ] return np.array(frequencies)
[docs] def get_pop_fourier(t, average_pop, amplitudes, frequencies): """Calculates the population using Fourier series. Parameters ---------- t : float Time variable. average_pop : float Average population. amplitudes : np.ndarray Amplitudes for transitions. frequencies : np.ndarray Frequencies corresponding to energy level differences. Returns ------- float The population at time t. """ population = average_pop for amplitude, frequency in zip(amplitudes, frequencies): population += amplitude * np.cos(frequency * t) return population
[docs] def calc_ipr_hamiltonian(eigs): r"""Calculates the inverse participation ratio (IPR) for each eigenstate of the Hamiltonian. Parameters ---------- eigs : np.ndarray Eigenvector matrix. Returns ------- list of float The IPR values for each eigenstate. Notes ----- .. note:: The IPR is a measure of the localization of an eigenstate. It is defined as the sum of the squared coefficients of the eigenvector. The IPR ranges from 1 to N, where N is the dimension of the Hilbert space. The IPR values can be used to distinguish between localized and delocalized eigenstates. .. math:: \mathrm{IPR} = 1/\sum_{i=1}^{N} |c_i|^4. - Localized state: :math:`\mathrm{IPR} = 1/N` - Delocalized coherent state: :math:`\mathrm{IPR} = N` """ dims = eigs.shape[0] ratios = [] for idx in range(dims): ipr_val = 1 / np.sum(coeff**4 for coeff in eigs[:, idx]) ratios.append(ipr_val) return ratios
# ----------------------------------------------------------------------