Representing the Bloch-Redfield equation (Spins)
SpinBRNoiseOperator
: this Bath Mapper object is used to model noise in systems that involve spin particles, such as electrons or atomic nuclei. In the context of quantum computing spins are used to encode quantum information and can be represented by Pauli operators. Spin noise can affect the coherence and stability of quantum states, so accurately modeling this noise is important for applications in quantum computing.
Equation for spins
As described in the Background Physics section, the Bloch-Redfield equation reads as follows:
\[ \dot{\rho}(t) = - \frac{\mathrm{i}}{\hbar} \left[ H, \rho(t) \right] - \frac{1}{\hbar^2} \sum_{m} \left[S_m, \Lambda_m(t) \rho(t) - \rho(t) \Lambda_m^{\dagger}(t) \right] , \] with \( \Lambda_m(t) = \sum_n \int_{0}^{\infty} d \tau C_{m, n}(\tau) S_{n, I} (t - \tau) \).
In the Bath Mapper library, we represent part of this equation. The SpinBRNoiseOperator
represents
the spectral function, which is the Fourier transform of the correlation function in the time
domain, \(C_{m, n}(\tau)\).
The SpinBRNoiseOperator
The Hamiltonian representing the couplings between the system and the bath for which the Bloch-Redfield formalism holds can be written as:
\[ H_C = \sum_n T_n U_n \]
where \(T_n\) are system operators and \(U_n\) are bath operators. An example of a \(T_n U_n\) term would be \( \sigma_x^0 ( b_0^{\dagger} + b_0) \), where the bath is assumed to be bosonic. (Note that the nature of the bath does not enter the Bloch-Redfield equation, only the spectral function matters.) It is important to note that \(T_n\) terms cannot act on more than one spin in the Bath Mapper representation, i.e. terms such as \( \sigma_x^0 \sigma_x^1 \) are not allowed.
We can write the spectral function for a system of N spins with arbitrary coupling to a bath of bosonic modes, which respects the above equation as follows:
\[ S_{T_n, T^\prime_m}(\omega) = \int_{-\infty}^{\infty} dt ~ e^{\textrm{i} \omega t} \langle U_n(t) U^\prime_m(0) \rangle_0 \]
where \( \omega\) is the frequency of the bosonic modes, \(S_{T_n, T^\prime_m}\) is the spectral function of the system operators \(T_n\) and \(T^\prime_m\), and \(U_n(t)\) and \(U^\prime_m(t)\) are the bath operators. Examples for \(T_n\), \(T^\prime_m\), \(U_n\) and \(U^\prime_m\) are: \( T_n = \sigma_x^0 \), \( T^\prime_m = \sigma_x^1 \), \( U_n = b_{0}^\dagger + b_{0}\) and \( U^\prime_m = b_{0}^\dagger + b_{0} + b_{1}^\dagger + b_{1}\).
Using the SpinBRNoiseOperator
The SpinBRNoiseOperator
is initialized with a list of frequencies for which to store the spectra.
Internally, the SpinBRNoiseOperator
stores this list of frequencies, as well as a dictionary of
PauliProduct
pairs with their corresponding spectral function. Each spectral function must have the
same number of points as the number of frequencies, and can have complex values.
Additionally, the SpinBRNoiseOperator
has the following functions:
set
- this takes a key(str, str)
(representing the left and right PauliProducts) and a valueList[complex]
(representing the frequency-resolved spectral function corresponding to the key). It sets this combination of inputs in the internal dictionary.set_real
- this takes a key(str, str)
(representing the left and right PauliProducts) and a valueList[float]
(representing the frequency-resolved spectral function corresponding to the key). It sets the real part of a spectral function for two spin indices.set_imag
- this takes a key(str, str)
(representing the left and right PauliProducts) and a valueList[float]
(representing the frequency-resolved spectral function corresponding to the key). It sets the imaginary part of a spectral function.get
- this takes a key(str, str)
(representing the left and right PauliProducts) and returns the corresponding spectral function stored in the dictionary. If none is found, a list of zeroes is returned.get_real
- this takes a key(str, str)
(representing the left and right PauliProducts) and returns the real part of the corresponding spectral function stored in the dictionary. If none is found, a list of zeroes is returned.get_imag
- this takes a key(str, str)
(representing the left and right PauliProducts) and returns the imaginary part of the corresponding spectral function stored in the dictionary. If none is found, a list of zeroes is returned.frequencies
- returns the frequencies for which the spectral functions are defined.get_spectral_function_matrix
- gets the matrix of the spectral function of a spin-system at a specific energy index. It takes a spectral function indexint
(the frequency index for which to return the matrix representation of the spectral function) and a number of spins (to build the correct size matrix) NOTE: The input for couplings between the system spins and the bath (bosons) is of the form: \(\sigma^i_\alpha (b^{\dagger} + b) \), where \(\sigma_\alpha \in \lbrace \sigma_x, \sigma_y, \sigma_z \rbrace \). Therefore, the matrix we build is of size \(3N \times 3N\) where \(N\) is the number of system spins. The indexing of the columns is \(0X, 0Y, 0Z, 1X, 1Y, 1Z, ... (N-1)X, (N-1)Y, (N-1)Z \). The indexing of the rows is identical.resample
- this function takes a list of frequenciesList[float]
and resamples the current spectral functions according to this list of new frequencies.resample_interpolate
- this function takes a list of frequenciesList[float]
and resamples the current spectral functions via interpolation, according to this list of new frequencies.
Additionally, serialization functions such as to_json/from_json
and to_bincode/from_bincode
are available for
easy transfer of information.
Python example
Below is a python snippet showing how to initialize and interface with the SpinBRNoiseOperator.
from bath_mapper import SpinBRNoiseOperator
frequencies = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
br_operator = SpinBRNoiseOperator(frequencies)
z_z_spectral_function = [0.0, 0.0, 0.01, 0.012, 0.15, 0.28, 0.16, 0.08, 0.02, 0.01]
br_operator.set(("0Z", "0Z"), z_z_spectral_function)
assert br_operator.get_imag(("0Z", "0Z")) == [0.0 for _ in range(len(frequencies))]
assert br_operator.get(("0X", "0X")) == [0.0 for _ in range(len(frequencies))]
assert br_operator.frequencies() == frequencies
new_frequencies = [0, 0.025, 0.05, 0.075, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225]
new_br_operator = br_operator.resample_interpolate(new_frequencies)
print(new_br_operator.frequencies())
print(new_br_operator.get(("0Z", "0Z")))
SpinLindbladNoiseOperator vs SpinBRNoiseOperator
As described in the Background Physics section, either the Bloch-Redfield master equation or the Lindblad master equation can be used to describe open quantum systems depending on the context and assumptions. struqture is the quantum computing library by HQS that utilizes the Lindblad equation.
The struqture object SpinLindbladNoiseOperator
represents the noise part of the Lindblad master equation:
\[ \dot{\rho} = - \frac{\mathrm{i}}{\hbar} \left[ H, \rho(t) \right] - \sum_{ij} M_{ij} \left( A_i \rho A^\dagger_j - \frac{1}{2} A^\dagger_j A_i \rho -\frac{1}{2} \rho A^\dagger_j A_i \right) \equiv L[\rho] , \]
where \(\rho\) is the density matrix of the qubits (spins). Operators \(A_i\) offer a basis for representing the noise operators, while matrix \(M\) gives (generalized) noise rates.