def test_identity(self, n, dtype): """Check hafnian(I)=0""" A = dtype(np.identity(n)) rpt = np.ones([n], dtype=np.int32) haf = hafnian_repeated(A, rpt) assert np.allclose(haf, 0) haf = hafnian_repeated(A, rpt, loop=True) assert np.allclose(haf, 1)
def test_rpt_valid(self): """Check exception for rpt having invalid values""" A = np.array([[2, 1], [1, 3]]) with pytest.raises(ValueError): hafnian_repeated(A, [1, -1]) with pytest.raises(ValueError): hafnian_repeated(A, [1.1, 1])
def test_ones(self, n, dtype): """Check hafnian(J_2n)=(2n)!/(n!2^n)""" A = dtype(np.ones([2 * n, 2 * n])) rpt = np.ones([2 * n], dtype=np.int32) haf = hafnian_repeated(A, rpt) expected = fac(2 * n) / (fac(n) * (2**n)) assert np.allclose(haf, expected) A = dtype([[1]]) rpt = [2 * n] haf = hafnian_repeated(A, rpt) assert np.allclose(haf, expected)
def test_real(self): """Check hafnian_repeated(A)=haf_real(A) for a random real matrix. """ A = np.random.random([6, 6]) A += A.T haf = hafnian_repeated(A, [1] * 6) expected = haf_rpt_real(np.float64(A), np.ones([6], dtype=np.int32)) assert np.allclose(haf, expected) A = np.random.random([6, 6]) A += A.T haf = hafnian_repeated(np.complex128(A), [1] * 6) expected = haf_rpt_real(np.float64(A), np.ones([6], dtype=np.int32)) assert np.allclose(haf, expected)
def test_block_ones(self, n, dtype): """Check hafnian([[0, I_n], [I_n, 0]])=n!""" O = np.zeros([n, n]) B = np.ones([n, n]) A = np.vstack([np.hstack([O, B]), np.hstack([B, O])]) A = dtype(A) rpt = np.ones([2 * n], dtype=np.int32) haf = hafnian_repeated(A, rpt) expected = float(fac(n)) assert np.allclose(haf, expected) A = np.array([[0, 1], [1, 0]], dtype=np.complex128) rpt = np.array([n, n], dtype=np.int32) haf = hafnian_repeated(A, rpt) assert np.allclose(haf, expected)
def test_rpt_zero(self): """Check 2x2 hafnian when rpt is all 0""" A = np.array([[2, 1], [1, 3]]) rpt = [0, 0] res = hafnian_repeated(A, rpt) assert res == 1.0
def test_ones_loop(self, n, dtype): """Check loop hafnian(J_n)=T(n)""" A = dtype(np.ones([n, n])) rpt = np.ones([n], dtype=np.int32) haf = hafnian_repeated(A, rpt, loop=True) expected = T[n] assert np.allclose(haf, expected)
def test_4x4(self, random_matrix): """Check 4x4 hafnian""" A = random_matrix(4) rpt = np.ones([4], dtype=np.int32) haf = hafnian_repeated(A, rpt) expected = A[0, 1] * A[2, 3] + A[0, 2] * A[1, 3] + A[0, 3] * A[1, 2] assert np.allclose(haf, expected)
def test_4x4_loop(self, random_matrix): """Check 4x4 loop hafnian""" A = random_matrix(4) rpt = np.ones([4], dtype=np.int32) haf = hafnian_repeated(A, rpt, loop=True) expected = (A[0, 1] * A[2, 3] + A[0, 2] * A[1, 3] + A[0, 3] * A[1, 2] + A[0, 0] * A[1, 1] * A[2, 3] + A[0, 1] * A[2, 2] * A[3, 3] + A[0, 2] * A[1, 1] * A[3, 3] + A[0, 0] * A[2, 2] * A[1, 3] + A[0, 0] * A[3, 3] * A[1, 2] + A[0, 3] * A[1, 1] * A[2, 2] + A[0, 0] * A[1, 1] * A[2, 2] * A[3, 3]) assert np.allclose(haf, expected)
def test_hafnian_batched(): """Test hafnian_batched against hafnian_repeated for a random symmetric matrix""" n_modes = 4 A = np.random.rand(n_modes, n_modes) + 1j * np.random.rand(n_modes, n_modes) A += A.T n_photon = 5 v1 = np.array([ hafnian_repeated(A, q) for q in product(np.arange(n_photon), repeat=n_modes) ]) assert np.allclose(hafnian_batched(A, n_photon, make_tensor=False), v1)
def test_outer_product(self, n, dtype): r"""Check that hafnian(x \otimes x) = hafnian(J_2n)*prod(x)""" x = np.random.rand(2 * n) + 1j * np.random.rand(2 * n) if not np.iscomplex(dtype()): x = x.real x = dtype(x) A = np.outer(x, x) rpt = np.ones([2 * n], dtype=np.int32) haf = hafnian_repeated(A, rpt) expected = np.prod(x) * fac(2 * n) / (fac(n) * (2**n)) assert np.allclose(haf, expected)
def test_hafnian_batched_zero_loops_no_edges(): """Test hafnian_batched with loops against hafnian_repeated with loops for a the zero matrix and a loops """ n_modes = 4 A = np.zeros([n_modes, n_modes], dtype=complex) n_photon = 5 v1 = np.array([ hafnian_repeated(A, q, loop=True) for q in product(np.arange(n_photon), repeat=n_modes) ]) expected = hafnian_batched(A, n_photon, make_tensor=False) assert np.allclose(expected, v1)
def test_hafnian_batched_loops_no_edges(): """Test hafnian_batched with loops against hafnian_repeated with loops for a random symmetric matrix and a random vector of loops """ n_modes = 4 A = np.zeros([n_modes, n_modes], dtype=complex) mu = np.random.rand(n_modes) + 1j * np.random.rand(n_modes) n_photon = 5 v1 = np.array([ hafnian_repeated(A, q, mu=mu, loop=True) for q in product(np.arange(n_photon), repeat=n_modes) ]) expected = hafnian_batched(A, n_photon, mu=mu, make_tensor=False) assert np.allclose(expected, v1)
def test_array_exception(self): """Check exception for non-matrix argument""" with pytest.raises(TypeError): hafnian_repeated(1, [1])
def test_2x2_loop(self, random_matrix): """Check 2x2 loop hafnian""" A = random_matrix(2) rpt = np.ones([2], dtype=np.int32) haf = hafnian_repeated(A, rpt, loop=True) assert np.allclose(haf, A[0, 1] + A[0, 0] * A[1, 1])
def test_3x3(self): """Check 3x3 hafnian""" A = np.ones([3, 3]) haf = hafnian_repeated(A, [1] * 3) assert haf == 0.0
def test_non_symmetric_exception(self): """Check exception for non-symmetric matrix""" A = np.ones([4, 4]) A[0, 1] = 0.0 with pytest.raises(ValueError): hafnian_repeated(A, [1] * 4)
def test_nan(self): """Check exception for non-finite matrix""" A = np.array([[2, 1], [1, np.nan]]) with pytest.raises(ValueError): hafnian_repeated(A, [1, 1])
def test_rpt_length(self): """Check exception for rpt having incorrect length""" A = np.array([[2, 1], [1, 3]]) with pytest.raises(ValueError): hafnian_repeated(A, [1])
def test_square_exception(self): """Check exception for non-square argument""" A = np.zeros([2, 3]) with pytest.raises(ValueError): hafnian_repeated(A, [1] * 2)
def test_2x2(self, random_matrix): """Check 2x2 hafnian""" A = random_matrix(2) rpt = np.ones([2], dtype=np.int32) haf = hafnian_repeated(A, rpt) assert np.allclose(haf, A[0, 1])