def test_disp_torontonian_two_mode(scale): """Calculates the probability of clicking for a two mode state""" cv = random_covariance(2) mu = scale * (2 * np.random.rand(4) - 1) prob_click = threshold_detection_prob(mu, cv, [1, 1]) mu0, cv0 = reduced_gaussian(mu, cv, [0]) mu1, cv1 = reduced_gaussian(mu, cv, [1]) expected = ( 1 - density_matrix_element(mu0, cv0, [0], [0]) - density_matrix_element(mu1, cv1, [0], [0]) + density_matrix_element(mu, cv, [0, 0], [0, 0]) ) assert np.allclose(expected, prob_click)
def test_displaced_two_mode_state_hafnian(self, sample_func): """Test the sampling routines by comparing the photon number frequencies and the exact probability distribution of a two mode coherent state """ n_samples = 1000 n_cut = 6 sigma = np.identity(4) mean = 5 * np.array([0.1, 0.25, 0.1, 0.25]) samples = sample_func(sigma, samples=n_samples, mean=mean, cutoff=n_cut) # samples = hafnian_sample_classical_state(sigma, mean = mean, samples = n_samples) probs = np.real_if_close( np.array([[ density_matrix_element(mean, sigma, [i, j], [i, j]) for i in range(n_cut) ] for j in range(n_cut)])) freq, _, _ = np.histogram2d(samples[:, 1], samples[:, 0], bins=np.arange(0, n_cut + 1)) rel_freq = freq / n_samples assert np.allclose(rel_freq, probs, rtol=rel_tol / np.sqrt(n_samples), atol=rel_tol / np.sqrt(n_samples))
def test_displaced_two_mode_squeezed_state_hafnian(self): """Test the sampling routines by comparing the photon number frequencies and the exact probability distribution of a displaced two mode squeezed vacuum state """ n_samples = 1000 n_cut = 10 mean_n = 1 r = np.arcsinh(np.sqrt(mean_n)) c = np.cosh(2 * r) s = np.sinh(2 * r) sigma = np.array([[c, s, 0, 0], [s, c, 0, 0], [0, 0, c, -s], [0, 0, -s, c]]) mean = 2 * np.array([0.1, 0.25, 0.1, 0.25]) samples = hafnian_sample_state(sigma, samples=n_samples, mean=mean, cutoff=n_cut) probs = np.real_if_close( np.array([[ density_matrix_element(mean, sigma, [i, j], [i, j]) for i in range(n_cut) ] for j in range(n_cut)])) freq, _, _ = np.histogram2d(samples[:, 1], samples[:, 0], bins=np.arange(0, n_cut + 1)) rel_freq = freq / n_samples assert np.allclose(rel_freq, probs, rtol=rel_tol / np.sqrt(n_samples), atol=rel_tol / np.sqrt(n_samples))
def test_disp_torontonian_single_mode(scale): """Calculates the probability of clicking for a single mode state""" cv = random_covariance(1) mu = scale * (2 * np.random.rand(2) - 1) prob_click = threshold_detection_prob(mu, cv, np.array([1])) expected = 1 - density_matrix_element(mu, cv, [0], [0]) assert np.allclose(prob_click, expected)
def fock_prob(mu, cov, ocp): """ Calculates the probability of measuring the gaussian state s2 in the photon number occupation pattern ocp""" if is_pure_cov(cov): return np.abs(pure_state_amplitude(mu, cov, ocp, check_purity=False)) ** 2 return density_matrix_element(mu, cov, list(ocp), list(ocp)).real
def test_density_matrix_element_no_disp(t): """Test density matrix elements for a state with no displacement""" beta = Beta(np.zeros([6])) Q = Qmat(V) el = t[0] ex = t[1] res = density_matrix_element(Means(beta), Covmat(Q), el[0], el[1]) assert np.allclose(ex, res)
def test_density_matrix_element_vacuum(): """Test density matrix elements for the vacuum""" Q = np.identity(2) beta = np.zeros([2]) el = [[0], [0]] ex = 1 res = density_matrix_element(Means(beta), Covmat(Q), el[0], el[1]) assert np.allclose(ex, res) el = [[1], [1]] # res = density_matrix_element(beta, A, Q, el[0], el[1]) res = density_matrix_element(Means(beta), Covmat(Q), el[0], el[1]) assert np.allclose(0, res) el = [[1], [0]] # res = density_matrix_element(beta, A, Q, el[0], el[1]) res = density_matrix_element(Means(beta), Covmat(Q), el[0], el[1]) assert np.allclose(0, res)
def marginals(mu: np.ndarray, V: np.ndarray, n_max: int, hbar: float = 2.0) -> np.ndarray: r"""Generate single-mode marginal distributions from the displacement vector and covariance matrix of a Gaussian state. **Example usage:** >>> mu = np.array([0.00000000, 2.82842712, 0.00000000, ... 0.00000000, 0.00000000, 0.00000000]) >>> V = np.array([[1.0, 0.0, 0.0, 0.0, 0.0, 0.0], ... [0.0, 1.0, 0.0, 0.0, 0.0, 0.0], ... [0.0, 0.0, 1.0, 0.0, 0.0, 0.0], ... [0.0, 0.0, 0.0, 1.0, 0.0, 0.0], ... [0.0, 0.0, 0.0, 0.0, 1.0, 0.0], ... [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]]) >>> n_max = 10 >>> marginals(mu, V, n_max) array([[1.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [1.35335284e-01, 2.70670567e-01, 2.70670566e-01, 1.80447044e-01, 9.02235216e-02, 3.60894085e-02, 1.20298028e-02, 3.43708650e-03, 8.59271622e-04, 1.90949249e-04], [1.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00]]) Args: mu (array): displacement vector V (array): covariance matrix n_max (int): maximum number of vibrational quanta in the distribution hbar (float): the value of :math:`\hbar` in the commutation relation :math:`[\x,\p]=i\hbar`. Returns: array[list[float]]: marginal distributions """ if not V.shape[0] == V.shape[1]: raise ValueError("The covariance matrix must be a square matrix") if not len(mu) == len(V): raise ValueError( "The dimension of the displacement vector and the covariance matrix must be equal" ) if n_max <= 0: raise ValueError( "The number of vibrational states must be larger than zero") n_modes = len(mu) // 2 p = np.zeros((n_modes, n_max)) for mode in range(n_modes): mui, vi = quantum.reduced_gaussian(mu, V, mode) for i in range(n_max): p[mode, i] = np.real( quantum.density_matrix_element(mui, vi, [i], [i], hbar=hbar)) return p
def get_probability(self, pattern: List[int]): """ :param pattern: a list of photon counts (per mode) :return: the probability of the given photon counting event """ return quantum.density_matrix_element(self.mu, self.cov, pattern, pattern).real