import numpy as np
import random
from qutip import Qobj, coherent, fock, thermal_dm, rand_dm, ket2dm, qfunc
import warnings
from qsttoolkit.data.states import cat_state, binomial_state, num_state, gkp_state
from qsttoolkit.data.num_state_coeffs import num_type_to_param
from qsttoolkit.utils import _range_error, _random_complex
[docs]
class States:
"""
Skeleton class for a set of quantum states, with methods for computing various representations and measurement functions.
Attributes
----------
n_states : int
Number of states to generate.
dim : int
Hilbert space dimensionality.
"""
def __init__(self, n_states: int, dim: int):
"""Initializes the States object with the given parameters."""
if not isinstance(dim, int): raise ValueError("dim must be an integer.")
if not isinstance(n_states, int): raise ValueError("n_states must be an integer.")
self.n_states = n_states
self.dim = dim
self.states = []
self.params = []
[docs]
def normalize(self):
"""Normalizes the states within the self.states attribute."""
self.states = [state.unit() for state in self.states]
[docs]
def normalise(self):
"""Deprecated alias for the normalize method."""
warnings.warn("normalise is deprecated and will be removed in a future version. Please use normalize instead.", DeprecationWarning, stacklevel=2)
self.normalize()
[docs]
def density_matrices(self) -> list[Qobj]:
"""
Returns the density matrices.
Returns
-------
list[Qobj]
Density matrices of the states.
"""
return [ket2dm(state) for state in self.states]
[docs]
def gen_Q(self, xgrid: np.ndarray, pgrid: np.ndarray) -> list[np.ndarray]:
"""
Generates the Husimi Q function images for the states.
Parameters
----------
xgrid : np.ndarray
Grid for the real part of the coherent state parameter.
pgrid : np.ndarray
Grid for the imaginary part of the coherent state parameter.
Returns
-------
list[np.ndarray]
Husimi Q function images for the states.
"""
return [qfunc(state, xgrid, pgrid) for state in self.states]
[docs]
class FockStates(States):
"""
A class to produce batches of Fock states with randomized parameters within a given range.
Attributes
----------
n_states : int
Number of Fock states to generate.
dim : int
Hilbert space dimensionality.
n_range : list[int, int]
Range of photon numbers n.
"""
def __init__(self, n_states: int, dim: int, n_range: list[int, int], N=None):
"""Initializes the FockStates object with the given parameters."""
if not dim:
if N:
dim = N
warnings.warn("N is deprecated and will be removed in a future version. Please use dim instead.", DeprecationWarning, stacklevel=2)
else:
raise ValueError("dim must be specified.")
super().__init__(n_states, dim)
_range_error(n_range, integers=True)
if n_range[1] > dim:
raise ValueError(f"max_n ({n_range[1]}) cannot be greater than dim ({dim})")
self.n_range = n_range
self.init_states()
[docs]
def init_states(self):
"""Generates the Fock states with the given parameters."""
n_values = np.random.randint(self.n_range[0], self.n_range[1], self.n_states)
self.states = [fock(self.dim, n) for n in n_values]
self.params = n_values
self.normalize()
[docs]
class CoherentStates(States):
"""
A class to produce batches of coherent states with randomized parameters within a given range.
Attributes
----------
n_states : int
Number of coherent states to generate.
dim : int
Hilbert space dimensionality.
alpha_magnitude_range : list[float, float]
Range of magnitudes for the phase space position parameter alpha.
"""
def __init__(self, n_states: int, dim: int, alpha_magnitude_range: list[float, float], N=None):
"""Initializes the CoherentStates object with the given parameters."""
if not dim:
if N:
dim = N
warnings.warn("N is deprecated and will be removed in a future version. Please use dim instead.", DeprecationWarning, stacklevel=2)
else:
raise ValueError("dim must be specified.")
super().__init__(n_states, dim)
_range_error(alpha_magnitude_range)
self.alpha_magnitude_range = alpha_magnitude_range
self.init_states()
[docs]
def init_states(self):
"""Generates the coherent states with the given parameters."""
for _ in range(self.n_states):
alpha = _random_complex(self.alpha_magnitude_range)
self.states.append(coherent(self.dim, alpha))
self.params.append(alpha)
self.normalize()
[docs]
class ThermalStates(States):
"""
A class to produce batches of thermal states with randomized parameters within a given range.
Attributes
----------
n_states : int
Number of thermal states to generate.
dim : int
Hilbert space dimensionality.
nbar_range : list[float, float]
Range of mean photon numbers nbar.
"""
def __init__(self, n_states: int, dim: int, nbar_range: list[float, float], N=None):
"""Initializes the ThermalStates object with the given parameters."""
if not dim:
if N:
dim = N
warnings.warn("N is deprecated and will be removed in a future version. Please use dim instead.", DeprecationWarning, stacklevel=2)
else:
raise ValueError("dim must be specified.")
super().__init__(n_states, dim)
_range_error(nbar_range)
self.nbar_range = nbar_range
self.init_states()
[docs]
def init_states(self):
"""Generates the thermal states with the given parameters."""
nbar_values = np.random.randint(self.nbar_range[0], self.nbar_range[1], self.n_states)
self.states = [thermal_dm(self.dim, nbar) for nbar in nbar_values]
self.params = nbar_values
warnings.warn("thermal states are currently initialized as density matrices. Calling the product of the .density_matrices() method is equivalent to simply calling .states() attribute. This may change in the future.")
[docs]
def density_matrices(self):
"""Overrides the parent method .density_matrices() as thermal states are initialized as density matrices."""
return self.states
[docs]
class NumStates(States):
"""
A class to produce batches of specific bosonic code states numerically optimized for quantum error correction.
Attributes
----------
n_states : int
Number of num states to generate.
dim : int
Hilbert space dimensionality.
types : list[str]
Types of num states to generate. Must be one of '17', 'M', 'P', 'P2', or 'M2'.
"""
def __init__(self, n_states: int, dim: int, types: list[str], N=None):
"""Initializes the NumStates object with the given parameters."""
if not dim:
if N:
dim = N
warnings.warn("N is deprecated and will be removed in a future version. Please use dim instead.", DeprecationWarning, stacklevel=2)
else:
raise ValueError("dim must be specified.")
super().__init__(n_states, dim)
self.types = types
self.init_states()
[docs]
def init_states(self):
"""Generates the num states with the given parameters."""
for _ in range(int(self.n_states)):
type_choice = random.choice(self.types)
self.states.append(num_state(type_choice, self.dim))
self.params.append(num_type_to_param[type_choice])
self.normalize()
[docs]
class BinomialStates(States):
"""
A class to produce batches of binomial states with randomized parameters within a given range.
Attributes
----------
n_states : int
Number of binomial states to generate.
dim : int
Hilbert space dimensionality.
S_range : list[int, int]
Range of the S parameter.
mu_range : list[int, int]
Range of the logical encoding parameter mu.
"""
def __init__(self, n_states: int, dim: int, S_range: list[int, int], mu_range: list[int, int], N=None):
"""Initializes the BinomialStates object with the given parameters."""
if not dim:
if N:
dim = N
warnings.warn("N is deprecated and will be removed in a future version. Please use dim instead.", DeprecationWarning, stacklevel=2)
else:
raise ValueError("dim must be specified.")
super().__init__(n_states, dim)
_range_error(S_range, integers=True)
_range_error(mu_range, integers=True)
self.S_range = S_range
self.SN_combs = [
(S, N)
for S in range(S_range[0], S_range[1] + 1)
for N in range(2, dim // (S + 1))
]
self.mu_range = mu_range
self.init_states()
[docs]
def init_states(self):
"""Generates the binomial states with the given parameters."""
for _ in range(self.n_states):
S, N = random.choice(self.SN_combs)
mu = random.randint(self.mu_range[0], self.mu_range[1])
self.states.append(binomial_state(self.dim, S, N, mu))
self.params.append(S)
self.normalize()
[docs]
class CatStates(States):
"""
A class to produce batches of cat states with randomized parameters within a given range.
Attributes
----------
n_states : int
Number of cat states to generate.
dim : int
Hilbert space dimensionality.
alpha_magnitude_range : list[float, float]
Range of magnitudes for the coherent state parameter alpha.
"""
def __init__(self, n_states: int, dim: int, alpha_magnitude_range: list[float, float], N=None):
"""Initializes the CatStates object with the given parameters."""
if not dim:
if N:
dim = N
warnings.warn("N is deprecated and will be removed in a future version. Please use dim instead.", DeprecationWarning, stacklevel=2)
else:
raise ValueError("dim must be specified.")
super().__init__(n_states, dim)
_range_error(alpha_magnitude_range)
self.alpha_magnitude_range = alpha_magnitude_range
self.init_states()
[docs]
def init_states(self):
"""Generates the cat states with the given parameters."""
for _ in range(self.n_states):
alpha = _random_complex(self.alpha_magnitude_range)
self.states.append(cat_state(self.dim, alpha))
self.params.append(alpha)
self.normalize()
[docs]
class GKPStates(States):
"""
A class to produce batches of Gottesman-Kitaev-Preskill (GKP) states with randomized parameters within a given range.
Attributes
----------
n_states : int
Number of GKP states to generate.
dim : int
Hilbert space dimensionality.
n1_range : list[int, int]
Range of grid parameter 1.
n2_range : list[int, int]
Range of grid parameter 2.
delta_range : list[float, float]
Range of the real normalisation parameter delta.
mu_range : list[int, int]
Range of the logical encoding parameter mu.
"""
def __init__(self, n_states: int, dim: int, n1_range: list[int, int], n2_range: list[int, int], delta_range: list[float, float], mu_range: list[int, int], N=None):
"""Initializes the GKPStates object with the given parameters."""
if not dim:
if N:
dim = N
warnings.warn("N is deprecated and will be removed in a future version. Please use dim instead.", DeprecationWarning, stacklevel=2)
else:
raise ValueError("dim must be specified.")
super().__init__(n_states, dim)
_range_error(n1_range, integers=True, positive=False)
_range_error(n2_range, integers=True, positive=False)
_range_error(delta_range)
_range_error(mu_range, integers=True)
self.n1_range = n1_range
self.n2_range = n2_range
self.delta_range = delta_range
self.mu_range = mu_range
self.init_states()
[docs]
def init_states(self):
"""Generates the GKP states with the given parameters."""
for _ in range(self.n_states):
delta = random.uniform(self.delta_range[0], self.delta_range[1])
mu = random.randint(self.mu_range[0], self.mu_range[1])
self.states.append(gkp_state(self.dim, self.n1_range, self.n2_range, delta, mu))
self.params.append(delta)
self.normalize()
[docs]
class RandomStates(States):
"""
A class to produce random states using QuTiP's rand_dm function.
Attributes
----------
n_states : int
Number of random states to generate.
dim : int
Hilbert space dimensionality.
"""
def __init__(self, n_states: int, dim: int, N=None):
"""Initializes the RandomStates object with the given parameters."""
if not dim:
if N:
dim = N
warnings.warn("N is deprecated and will be removed in a future version. Please use dim instead.", DeprecationWarning, stacklevel=2)
else:
raise ValueError("dim must be specified.")
super().__init__(n_states, dim)
self.init_states()
[docs]
def init_states(self):
"""Generates the random states with the given parameters"""
self.states = [rand_dm(self.dim) for _ in range(self.n_states)]
self.params = [0 for _ in range(self.n_states)]
warnings.warn("Random states are currently initialized as density matrices. Calling the product of the .density_matrices() method is equivalent to simply calling .states() attribute. This may change in the future.")
[docs]
def density_matrices(self):
"""Overrides the parent method .density_matrices() as random states are initialized as density matrices."""
return self.states