def test_init_exceptions(self): M = 5 st = np.array([], dtype=float) hs = HilbertSpace([make_space_fermion(i) for i in range(M)]) # Multiple fermions with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(M, M + 1)): NFermionSectorViewR(st, hs, M + 1) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(M, M + 1)): NFermionSectorViewC(st, hs, M + 1) # Fermions and bosons hs.add(make_space_boson(2, 5)) hs.add(make_space_boson(3, 6)) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(M, M + 1)): NFermionSectorViewR(st, hs, M + 1) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(M, M + 1)): NFermionSectorViewC(st, hs, M + 1) # Purely bosonic Hilbert space hs_b = HilbertSpace([make_space_boson(2, 0), make_space_boson(3, 1)]) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): NFermionSectorViewR(st, hs_b, 1) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): NFermionSectorViewC(st, hs_b, 1)
def test_overload_selection(self): expr = 6 * c_dag("dn") - 6 * c("up") hs = HilbertSpace(expr) lop = LOperatorR(expr, hs) src_int = np.array([1, 1, 1, 1], dtype=int) src_real = np.array([1, 1, 1, 1], dtype=float) src_complex = np.array([1, 1, 1, 1], dtype=complex) ref_real = np.array([-6, 12, 0, 6], dtype=float) ref_complex = np.array([-6, 12, 0, 6], dtype=complex) self.assertEqual((lop * src_int).dtype, np.float64) self.assertEqual((lop * src_real).dtype, np.float64) self.assertEqual((lop * src_complex).dtype, np.complex128) dst_int = np.zeros(4, dtype=int) dst_real = np.zeros(4, dtype=float) dst_complex = np.zeros(4, dtype=complex) self.assertRaises(TypeError, lop, src_int, dst_int) self.assertRaises(TypeError, lop, src_real, dst_int) self.assertRaises(TypeError, lop, src_complex, dst_int) self.assertRaises(TypeError, lop, src_complex, dst_real) lop(src_int, dst_real) assert_equal(dst_real, ref_real) lop(src_int, dst_complex) assert_equal(dst_complex, ref_complex) lop(src_real, dst_real) assert_equal(dst_real, ref_real) lop(src_real, dst_complex) assert_equal(dst_complex, ref_complex) lop(src_complex, dst_complex) assert_equal(dst_complex, ref_complex) expr = 6j * c_dag("dn") - 6j * c("up") hs = HilbertSpace(expr) lop = LOperatorC(expr, hs) self.assertEqual((lop * src_int).dtype, np.complex128) self.assertEqual((lop * src_real).dtype, np.complex128) self.assertEqual((lop * src_complex).dtype, np.complex128) ref_complex = np.array([-6j, 12j, 0, 6j], dtype=complex) self.assertRaises(TypeError, lop, src_int, dst_int) self.assertRaises(TypeError, lop, src_real, dst_int) self.assertRaises(TypeError, lop, src_complex, dst_int) self.assertRaises(TypeError, lop, src_int, dst_real) self.assertRaises(TypeError, lop, src_real, dst_real) self.assertRaises(TypeError, lop, src_complex, dst_real) lop(src_int, dst_complex) assert_equal(dst_complex, ref_complex) lop(src_real, dst_complex) assert_equal(dst_complex, ref_complex) lop(src_complex, dst_complex) assert_equal(dst_complex, ref_complex)
def test_equality(self): hs_empty = HilbertSpace() self.assertTrue(hs_empty == hs_empty) self.assertFalse(hs_empty != hs_empty) hs = HilbertSpace([ self.es_s32_i, self.es_s32_j, self.es_s1_i, self.es_s1_j, self.es_s_i, self.es_s_j, self.es_b_x, self.es_b_y, self.es_f_dn, self.es_f_up ]) self.assertTrue(hs == hs) self.assertFalse(hs != hs) self.assertFalse(hs == hs_empty) self.assertTrue(hs != hs_empty)
def setUpClass(cls): # Finite system of 4 fermions: 2 orbitals, two spin projections # Hamiltonian: spin flips cls.Hex = \ 2 * c_dag("up", 1) * c("up", 2) * c_dag("dn", 2) * c("dn", 1) \ + 2 * c_dag("up", 2) * c("up", 1) * c_dag("dn", 1) * c("dn", 2) cls.Hp = \ 2 * c_dag("up", 1) * c("up", 2) * c_dag("dn", 1) * c("dn", 2) \ + 2 * c_dag("up", 2) * c("up", 1) * c_dag("dn", 2) * c("dn", 1) cls.hs = HilbertSpace(cls.Hex + cls.Hp) # 3 = 1 + 2 -> |dn>_1 |dn>_2 # 5 = 1 + 4 -> |dn>_1 |up>_1 # 6 = 2 + 4 -> |dn>_2 |up>_1 # 9 = 1 + 8 -> |dn>_1 |up>_2 # 10 = 2 + 8 -> |dn>_2 |up>_2 # 12 = 4 + 8 -> |up>_1 |up>_2 # Map all basis states with 2 electrons so that their indices # are contiguous cls.mapping = {i: j for j, i in enumerate([3, 5, 6, 9, 10, 12])} cls.mapper = BasisMapper([3, 5, 6, 9, 10, 12]) cls.st = np.array([0, 1, 2, 3, 4, 5], dtype=float)
def test_HilbertSpace(self): indices = [("dn", 0), ("dn", 1), ("up", 0), ("up", 1)] hs = HilbertSpace([make_space_fermion(*ind) for ind in indices]) for ind in indices: c_op = LOperatorR(c(*ind), hs) assert_equal(make_matrix(c_op, hs), self.c_mat(hs, *ind)) c_dag_op = LOperatorR(c_dag(*ind), hs) assert_equal(make_matrix(c_dag_op, hs), self.c_dag_mat(hs, *ind)) H1 = 1.0 * (c_dag("up", 0) * c("up", 1) + c_dag("up", 1) * c("up", 0)) H1 += 2.0 * (c_dag("dn", 0) * c("dn", 1) + c_dag("dn", 1) * c("dn", 0)) H1op = LOperatorR(H1, hs) ref1 = 1.0 * (self.c_dag_mat(hs, "up", 0) @ self.c_mat(hs, "up", 1) + self.c_dag_mat(hs, "up", 1) @ self.c_mat(hs, "up", 0)) ref1 += 2.0 * (self.c_dag_mat(hs, "dn", 0) @ self.c_mat(hs, "dn", 1) + self.c_dag_mat(hs, "dn", 1) @ self.c_mat(hs, "dn", 0)) assert_equal(make_matrix(H1op, hs), ref1) H2 = 1.0j * (c_dag("up", 0) * c("up", 1) + c_dag("up", 1) * c("up", 0)) H2 += 2.0 * (c_dag("dn", 0) * c("dn", 1) + c_dag("dn", 1) * c("dn", 0)) H2op = LOperatorC(H2, hs) ref2 = 1.0j * (self.c_dag_mat(hs, "up", 0) @ self.c_mat(hs, "up", 1) + self.c_dag_mat(hs, "up", 1) @ self.c_mat(hs, "up", 0)) ref2 += 2.0 * (self.c_dag_mat(hs, "dn", 0) @ self.c_mat(hs, "dn", 1) + self.c_dag_mat(hs, "dn", 1) @ self.c_mat(hs, "dn", 0)) assert_equal(make_matrix(H2op, hs), ref2)
def test_basis_state_indices(self): indices = [("dn", 0), ("dn", 1), ("up", 0), ("up", 1)] hs = HilbertSpace([make_space_fermion(*ind) for ind in indices]) # Basis of the N=2 sector basis_state_indices = [3, 5, 6, 9, 10, 12] H1 = 1.0 * (c_dag("up", 0) * c("up", 1) + c_dag("up", 1) * c("up", 0)) H1 += 2.0 * (c_dag("dn", 0) * c("dn", 1) + c_dag("dn", 1) * c("dn", 0)) H1op = LOperatorR(H1, hs) ref1 = 1.0 * (self.c_dag_mat(hs, "up", 0) @ self.c_mat(hs, "up", 1) + self.c_dag_mat(hs, "up", 1) @ self.c_mat(hs, "up", 0)) ref1 += 2.0 * (self.c_dag_mat(hs, "dn", 0) @ self.c_mat(hs, "dn", 1) + self.c_dag_mat(hs, "dn", 1) @ self.c_mat(hs, "dn", 0)) ref1 = ref1[basis_state_indices, :][:, basis_state_indices] assert_equal(make_matrix(H1op, basis_state_indices), ref1) H2 = 1.0j * (c_dag("up", 0) * c("up", 1) + c_dag("up", 1) * c("up", 0)) H2 += 2.0 * (c_dag("dn", 0) * c("dn", 1) + c_dag("dn", 1) * c("dn", 0)) H2op = LOperatorC(H2, hs) ref2 = 1.0j * (self.c_dag_mat(hs, "up", 0) @ self.c_mat(hs, "up", 1) + self.c_dag_mat(hs, "up", 1) @ self.c_mat(hs, "up", 0)) ref2 += 2.0 * (self.c_dag_mat(hs, "dn", 0) @ self.c_mat(hs, "dn", 1) + self.c_dag_mat(hs, "dn", 1) @ self.c_mat(hs, "dn", 0)) ref2 = ref2[basis_state_indices, :][:, basis_state_indices] assert_equal(make_matrix(H2op, basis_state_indices), ref2)
def test_empty(self): expr0 = ExpressionR() hs = HilbertSpace(expr0) lop = LOperatorR(expr0, hs) sv = np.array([], dtype=float) assert_equal(lop * sv, sv) dst = np.array([], dtype=float) lop(sv, dst) assert_equal(sv, dst)
def test_loperator(self): M = 5 hs = HilbertSpace([make_space_boson(2, 0)]) for i in range(M): hs.add(make_space_fermion(i)) H = (n(0) + n(1) + n(2) + n(3) + n(4)) * (a_dag(0) + a(0)) for src_type, dst_type, lop_type in [(float, float, LOperatorR), (float, complex, LOperatorR), (complex, complex, LOperatorR), (float, complex, LOperatorC), (complex, complex, LOperatorC)]: src_view_type = NFermionSectorViewR if (src_type == float) \ else NFermionSectorViewC dst_view_type = NFermionSectorViewR if (dst_type == float) \ else NFermionSectorViewC Hop = lop_type(H if lop_type == LOperatorR else make_complex(H), hs) for N in range(M + 1): src = np.zeros(n_fermion_sector_size(hs, N), dtype=src_type) view_src = src_view_type(src, hs, N) dst = np.zeros(n_fermion_sector_size(hs, N), dtype=dst_type) view_dst = dst_view_type(dst, hs, N) # 1 boson, fermions in the first N modes index_in_f = sum(2**i for i in range(N)) src[view_src.map_index(index_in_f + (2**M))] = 1 Hop(view_src, view_dst) ref = np.zeros(n_fermion_sector_size(hs, N), dtype=dst_type) # 0 bosons ref[view_dst.map_index(index_in_f)] = N # 2 bosons ref[view_dst.map_index(index_in_f + (2 ** (M + 1)))] = \ N * np.sqrt(2) assert_allclose(dst, ref)
def test_compositions_bosons(self): hs = HilbertSpace(a_dag(1) + a_dag(2) + a_dag(3) + a_dag(4), 4) O_list = [LOperatorR(a_dag(1), hs), LOperatorR(a_dag(2), hs), LOperatorR(a_dag(3), hs), LOperatorR(a_dag(4), hs)] map_size_ref = [1, 4, 10, 20, 35, 56, 84, 120, 165, 220] for N in range(10): mapper = BasisMapper(O_list, hs, N) self.assertEqual(len(mapper), map_size_ref[N])
def test_n_fermion_sector_basis_states(self): M = 8 st = np.array([], dtype=float) hs = HilbertSpace() self.assertEqual(n_fermion_sector_basis_states(hs, 0), []) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_sector_basis_states(hs, 1) def build_basis_states_ref(hs, N): view = NFermionSectorViewR(st, hs, N) basis_states = [-1] * n_fermion_sector_size(hs, N) for index in range(hs.dim): if popcount(index, M) == N: basis_states[view.map_index(index)] = index return basis_states # Purely fermionic Hilbert spaces for i in range(M): hs.add(make_space_fermion(i)) for N in range(M + 1): ref = build_basis_states_ref(hs, N) self.assertEqual(n_fermion_sector_basis_states(hs, N), ref) # Fermions and bosons hs.add(make_space_boson(2, M)) hs.add(make_space_boson(2, M + 1)) for N in range(M + 1): ref = build_basis_states_ref(hs, N) self.assertEqual(n_fermion_sector_basis_states(hs, N), ref) # Purely bosonic Hilbert space hs_b = HilbertSpace([make_space_boson(2, 0), make_space_boson(3, 1)]) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_sector_basis_states(hs_b, 1) ref = list(range(n_fermion_sector_size(hs_b, 0))) self.assertEqual(n_fermion_sector_basis_states(hs_b, 0), ref)
def test_strided_arrays(self): expr = 6 * c_dag("dn") - 6 * c("up") hs = HilbertSpace(expr) lop = LOperatorR(expr, hs) src_real = 999 * np.ones((10, ), dtype=float) src_real[3:10:2] = 1 src_complex = np.array(src_real, dtype=complex) assert_equal(lop * src_real[3:10:2], np.array([-6, 12, 0, 6], dtype=float)) assert_equal(lop * src_complex[3:10:2], np.array([-6, 12, 0, 6], dtype=complex)) dst_real = 777 * np.ones((10, ), dtype=float) dst_complex = np.array(dst_real, dtype=complex) ref_real = np.array([777, 777, -6, 777, 12, 777, 0, 777, 6, 777], dtype=float) ref_complex = np.array(ref_real, dtype=complex) lop(src_real[3:10:2], dst_real[2:9:2]) assert_equal(dst_real, ref_real) lop(src_real[3:10:2], dst_complex[2:9:2]) assert_equal(dst_complex, ref_complex) lop(src_complex[3:10:2], dst_complex[2:9:2]) assert_equal(dst_complex, ref_complex) expr = 6j * c_dag("dn") - 6j * c("up") hs = HilbertSpace(expr) lop = LOperatorC(expr, hs) ref_complex = np.array([777, 777, -6j, 777, 12j, 777, 0, 777, 6j, 777], dtype=complex) lop(src_real[3:10:2], dst_complex[2:9:2]) assert_equal(dst_complex, ref_complex) lop(src_complex[3:10:2], dst_complex[2:9:2]) assert_equal(dst_complex, ref_complex)
def test_map_index(self): M = 8 st = np.array([], dtype=float) hs = HilbertSpace() def check_map_index(view, m, n): mapped_indices = [] for index in range(hs.dim): if popcount(index, m) == n: mapped_indices.append(view.map_index(index)) mapped_indices.sort() mapped_indices_ref = list(range(n_fermion_sector_size(hs, n))) self.assertEqual(mapped_indices, mapped_indices_ref) # Purely fermionic Hilbert spaces for i in range(M): hs.add(make_space_fermion(i)) for N in range(M + 1): check_map_index(NFermionSectorViewR(st, hs, N), M, N) check_map_index(NFermionSectorViewC(st, hs, N), M, N) # Fermions and bosons hs.add(make_space_boson(2, M)) hs.add(make_space_boson(2, M + 1)) for N in range(M + 1): check_map_index(NFermionSectorViewR(st, hs, N), M, N) check_map_index(NFermionSectorViewC(st, hs, N), M, N) # Purely bosonic Hilbert space hs_b = HilbertSpace([make_space_boson(2, 0), make_space_boson(3, 1)]) ref_indices = list(range(hs_b.dim)) view = NFermionSectorViewR(st, hs_b, 0) indices = [view.map_index(index) for index in range(hs_b.dim)] self.assertEqual(indices, ref_indices) view = NFermionSectorViewC(st, hs_b, 0) indices = [view.map_index(index) for index in range(hs_b.dim)] self.assertEqual(indices, ref_indices)
def test_LOperatorR(self): expr1 = 3 * c_dag("dn") expr2 = 3 * c("up") expr = 2 * expr1 - 2 * expr2 hs = HilbertSpace(expr) lop1 = LOperatorR(expr1, hs) lop2 = LOperatorR(expr2, hs) lop = LOperatorR(expr, hs) src = np.array([1, 1, 1, 1]) dst_real = np.zeros((4, ), dtype=float) dst_complex = np.zeros((4, ), dtype=complex) assert_equal(lop1 * src, np.array([0, 3, 0, 3])) lop1(src, dst_real) assert_equal(dst_real, np.array([0, 3, 0, 3])) lop1(src, dst_complex) assert_equal(dst_complex, np.array([0, 3, 0, 3], dtype=complex)) assert_equal(lop2 * src, np.array([3, -3, 0, 0])) lop2(src, dst_real) assert_equal(dst_real, np.array([3, -3, 0, 0])) lop2(src, dst_complex) assert_equal(dst_complex, np.array([3, -3, 0, 0], dtype=complex)) assert_equal(lop * src, np.array([-6, 12, 0, 6])) lop(src, dst_real) assert_equal(dst_real, np.array([-6, 12, 0, 6])) lop(src, dst_complex) assert_equal(dst_complex, np.array([-6, 12, 0, 6], dtype=complex)) src_complex = 1j * np.array([1, 1, 1, 1]) assert_equal(lop * src_complex, np.array([-6j, 12j, 0, 6j])) lop(src_complex, dst_complex) assert_equal(dst_complex, np.array([-6j, 12j, 0, 6j])) with self.assertRaisesRegex( RuntimeError, "^State vector must be a 1-dimensional array$"): lop * np.zeros((3, 3, 3)) with self.assertRaisesRegex( RuntimeError, "^Source state vector must be a 1-dimensional array$"): lop(np.zeros((3, 3, 3)), np.zeros((5, ))) with self.assertRaisesRegex( RuntimeError, "^Destination state vector must be a 1-dimensional array$"): lop(np.zeros((5, )), np.zeros((3, 3, 3)))
def test_left_right_basis_state_indices(self): indices = [("dn", 0), ("dn", 1), ("up", 0), ("up", 1)] hs = HilbertSpace([make_space_fermion(*ind) for ind in indices]) # Basis of the N=1 sector N1_basis_state_indices = [1, 2, 4, 8] # Basis of the N=2 sector N2_basis_state_indices = [3, 5, 6, 9, 10, 12] # Basis of the N=3 sector N3_basis_state_indices = [7, 11, 13, 14] for ind1, ind2 in product(indices, indices): op1 = LOperatorR(c(*ind1) * c(*ind2), hs) ref1 = self.c_mat(hs, *ind1) @ self.c_mat(hs, *ind2) ref1 = ref1[N1_basis_state_indices, :][:, N3_basis_state_indices] assert_equal( make_matrix(op1, N1_basis_state_indices, N3_basis_state_indices), ref1) op2 = LOperatorC(1j * c(*ind1) * c(*ind2), hs) ref2 = 1j * self.c_mat(hs, *ind1) @ self.c_mat(hs, *ind2) ref2 = ref2[N1_basis_state_indices, :][:, N3_basis_state_indices] assert_equal( make_matrix(op2, N1_basis_state_indices, N3_basis_state_indices), ref2) for ind in indices: op1 = LOperatorR(c(*ind), hs) ref1 = self.c_mat(hs, *ind) ref1 = ref1[N2_basis_state_indices, :][:, N3_basis_state_indices] assert_equal( make_matrix(op1, N2_basis_state_indices, N3_basis_state_indices), ref1) op2 = LOperatorC(1j * c(*ind), hs) ref2 = 1j * self.c_mat(hs, *ind) ref2 = ref2[N2_basis_state_indices, :][:, N3_basis_state_indices] assert_equal( make_matrix(op2, N2_basis_state_indices, N3_basis_state_indices), ref2)
def test_very_big_space(self): hs1 = HilbertSpace() for i in range(32): hs1.add(make_space_spin(3 / 2, "s", i)) with self.assertRaisesRegex( RuntimeError, "Hilbert space size is not representable by a 64-bit integer " "\\(n_bits = 66\\)"): hs1.add(make_space_spin(3 / 2, "s", 32)) expr = ExpressionR(1.0) for i in range(32): expr *= S_p("s", i, spin=3 / 2) hs2 = HilbertSpace(expr) self.assertEqual(hs2.total_n_bits, 64) expr *= S_p("s", 32, spin=3 / 2) with self.assertRaisesRegex( RuntimeError, "Hilbert space size is not representable by a 64-bit integer " "\\(n_bits = 66\\)"): HilbertSpace(expr)
def setUpClass(cls): # Parameters of the 3 orbital Hubbard-Kanamori atom cls.n_orbs = 3 cls.mu = 0.7 cls.U = 3.0 cls.J = 0.3 indices_up = [("up", o) for o in range(cls.n_orbs)] indices_dn = [("dn", o) for o in range(cls.n_orbs)] # Hamiltonian cls.H = dispersion(-cls.mu * np.ones(cls.n_orbs), indices=indices_up) cls.H += dispersion(-cls.mu * np.ones(cls.n_orbs), indices=indices_dn) cls.H += kanamori_int(cls.n_orbs, cls.U, cls.J, indices_up=indices_up, indices_dn=indices_dn) # Hilbert space cls.hs = HilbertSpace(cls.H) # Linear operator form of the Hamiltonian cls.Hop = LOperatorR(cls.H, cls.hs)
def test_map_index(self): st = np.array([], dtype=float) # Check that values returned by map_index() form a continuous # sequence [0; expected_multisector_size) def check_map_index(view, hs, selector, expected_multisector_size): mapped_indices = [] for index in range(hs.dim): if selector(index): mapped_indices.append(view.map_index(index)) mapped_indices.sort() mapped_indices_ref = list(range(expected_multisector_size)) self.assertEqual(mapped_indices, mapped_indices_ref) # # Purely fermionic Hilbert spaces # hs = HilbertSpace([make_space_fermion(i) for i in range(self.M_total)]) for ViewType in (NFermionMultiSectorViewR, NFermionMultiSectorViewC): for N in range(self.N5_max + 1): check_map_index(ViewType(st, hs, [self.sd5(N)]), hs, self.sd5_index_selector(N), 2**(self.M_total - 1)) for N1, N2 in product(range(self.Na_max + 1), range(self.Nb_max + 1)): check_map_index( ViewType(st, hs, [self.sda(N1), self.sdb(N2)]), hs, self.sdab_index_selector(N1, N2), comb(4, N1) * comb(4, N2) * (2**(self.M_total - 8))) for N1, N2, N3 in product(range(self.Na_max + 1), range(self.N5_max + 1), range(self.Nb_max + 1)): check_map_index( ViewType(st, hs, [self.sda(N1), self.sd5(N2), self.sdb(N3)]), hs, self.sda5b_index_selector(N1, N2, N3), comb(4, N1) * comb(4, N3) * (2**(self.M_total - 9))) # # Fermions and bosons # hs.add(make_space_boson(2, self.M_total)) hs.add(make_space_boson(2, self.M_total + 1)) M = self.M_total + 4 for ViewType in (NFermionMultiSectorViewR, NFermionMultiSectorViewC): for N in range(self.N5_max + 1): check_map_index(ViewType(st, hs, [self.sd5(N)]), hs, self.sd5_index_selector(N), 2**(M - 1)) for N1, N2 in product(range(self.Na_max + 1), range(self.Nb_max + 1)): check_map_index(ViewType( st, hs, [self.sda(N1), self.sdb(N2)]), hs, self.sdab_index_selector(N1, N2), comb(4, N1) * comb(4, N2) * (2**(M - 8))) for N1, N2, N3 in product(range(self.Na_max + 1), range(self.N5_max + 1), range(self.Nb_max + 1)): check_map_index( ViewType(st, hs, [self.sda(N1), self.sd5(N2), self.sdb(N3)]), hs, self.sda5b_index_selector(N1, N2, N3), comb(4, N1) * comb(4, N3) * (2**(M - 9))) # # Purely bosonic Hilbert space # hs_b = HilbertSpace([make_space_boson(2, 0), make_space_boson(3, 1)]) for ViewType in (NFermionMultiSectorViewR, NFermionMultiSectorViewC): view = ViewType(st, hs_b, [self.sde(0)]) for index in range(hs_b.dim): self.assertEqual(view.map_index(index), index)
def test_n_fermion_sector_size(self): hs = HilbertSpace() # Empty Hilbert space self.assertEqual(n_fermion_sector_size(hs, 0), 0) self.assertEqual(n_fermion_sector_size(hs, 1), 0) # Purely fermionic Hilbert spaces hs.add(make_space_fermion(0)) self.assertEqual(n_fermion_sector_size(hs, 0), 1) self.assertEqual(n_fermion_sector_size(hs, 1), 1) hs.add(make_space_fermion(1)) self.assertEqual(n_fermion_sector_size(hs, 0), 1) self.assertEqual(n_fermion_sector_size(hs, 1), 2) self.assertEqual(n_fermion_sector_size(hs, 2), 1) hs.add(make_space_fermion(2)) self.assertEqual(n_fermion_sector_size(hs, 0), 1) self.assertEqual(n_fermion_sector_size(hs, 1), 3) self.assertEqual(n_fermion_sector_size(hs, 2), 3) self.assertEqual(n_fermion_sector_size(hs, 3), 1) # Fermions and bosons hs.add(make_space_boson(4, 3)) self.assertEqual(n_fermion_sector_size(hs, 0), 16) self.assertEqual(n_fermion_sector_size(hs, 1), 48) self.assertEqual(n_fermion_sector_size(hs, 2), 48) self.assertEqual(n_fermion_sector_size(hs, 3), 16) # Purely bosonic Hilbert space hs_b = HilbertSpace([make_space_boson(2, 0), make_space_boson(3, 1)]) self.assertEqual(n_fermion_sector_size(hs_b, 0), 32) self.assertEqual(n_fermion_sector_size(hs_b, 1), 0)
# adjacency matrix of the lattice. hopping_matrix = -t * adjacency_matrix(lat).todense() H = tight_binding(hopping_matrix, indices=indices_up) \ + tight_binding(hopping_matrix, indices=indices_dn) # Add the chemical potential terms H += dispersion(-mu * np.ones(len(indices_up)), indices=indices_up) H += dispersion(-mu * np.ones(len(indices_dn)), indices=indices_dn) # Add the Hubbard interaction term H += hubbard_int(U * np.ones(len(indices_up)), indices_up=indices_up, indices_dn=indices_dn) # Analyze structure of H and construct a suitable Hilbert space. hs = HilbertSpace(H) print("Full Hilbert space dimension:", hs.dim) # Construct a linear operator corresponding to H and acting in the Hilbert # space 'hs'. H_op = LOperatorR(H, hs) # # Diagonalize the N = 2 sector of the model using 'NFermionSectorViewR' # N = 2 sector_size = n_fermion_sector_size(hs, N) print("Size of the N = 2 sector:", sector_size)
def test_attributes(self): hs = HilbertSpace([ self.es_s32_i, self.es_s32_j, self.es_s1_j, self.es_s_i, self.es_s_j, self.es_b_x, self.es_f_dn, self.es_f_up ]) self.assertEqual(len(hs), 8) self.assertEqual(hs.total_n_bits, 14) self.assertEqual(hs.dim, 16384) self.assertTrue(hs.has_algebra(FERMION)) self.assertTrue(hs.has_algebra(BOSON)) self.assertTrue(hs.has_algebra(SPIN)) self.assertEqual(hs.algebra_bit_range(FERMION), (0, 1)) self.assertEqual(hs.algebra_bit_range(BOSON), (2, 5)) self.assertEqual(hs.algebra_bit_range(SPIN), (6, 13)) self.assertTrue(self.es_f_dn in hs) self.assertEqual(hs.index(self.es_f_dn), 0) self.assertEqual(hs.bit_range(self.es_f_dn), (0, 0)) self.assertEqual(hs.basis_state_index(self.es_f_dn, 0), 0) self.assertEqual(hs.basis_state_index(self.es_f_dn, 1), 1) self.assertTrue(self.es_f_up in hs) self.assertEqual(hs.index(self.es_f_up), 1) self.assertEqual(hs.bit_range(self.es_f_up), (1, 1)) self.assertEqual(hs.basis_state_index(self.es_f_up, 0), 0) self.assertEqual(hs.basis_state_index(self.es_f_up, 1), 2) self.assertTrue(self.es_b_x in hs) self.assertEqual(hs.index(self.es_b_x), 2) self.assertEqual(hs.bit_range(self.es_b_x), (2, 5)) self.assertEqual(hs.basis_state_index(self.es_b_x, 0), 0) self.assertEqual(hs.basis_state_index(self.es_b_x, 1), 4) self.assertEqual(hs.basis_state_index(self.es_b_x, 5), 20) self.assertFalse(self.es_b_y in hs) with self.assertRaisesRegex(RuntimeError, "^Elementary space not found$"): hs.bit_range(self.es_b_y) self.assertTrue(self.es_s_i in hs) self.assertEqual(hs.index(self.es_s_i), 3) self.assertEqual(hs.bit_range(self.es_s_i), (6, 6)) self.assertEqual(hs.basis_state_index(self.es_s_i, 0), 0) self.assertEqual(hs.basis_state_index(self.es_s_i, 1), 64) self.assertTrue(self.es_s_j in hs) self.assertEqual(hs.index(self.es_s_j), 4) self.assertEqual(hs.bit_range(self.es_s_j), (7, 7)) self.assertFalse(self.es_s1_i in hs) with self.assertRaisesRegex(RuntimeError, "^Elementary space not found$"): hs.bit_range(self.es_s1_i) self.assertTrue(self.es_s1_j in hs) self.assertEqual(hs.index(self.es_s1_j), 5) self.assertEqual(hs.bit_range(self.es_s1_j), (8, 9)) self.assertEqual(hs.basis_state_index(self.es_s1_j, 0), 0) self.assertEqual(hs.basis_state_index(self.es_s1_j, 1), 256) self.assertEqual(hs.basis_state_index(self.es_s1_j, 2), 512) self.assertTrue(self.es_s32_i in hs) self.assertEqual(hs.index(self.es_s32_i), 6) self.assertEqual(hs.bit_range(self.es_s32_i), (10, 11)) self.assertEqual(hs.basis_state_index(self.es_s32_i, 0), 0) self.assertEqual(hs.basis_state_index(self.es_s32_i, 1), 1024) self.assertEqual(hs.basis_state_index(self.es_s32_i, 2), 2048) self.assertEqual(hs.basis_state_index(self.es_s32_i, 3), 3072) self.assertTrue(self.es_s32_j in hs) self.assertEqual(hs.index(self.es_s32_j), 7) self.assertEqual(hs.bit_range(self.es_s32_j), (12, 13)) self.assertEqual(hs.basis_state_index(self.es_s32_j, 0), 0) self.assertEqual(hs.basis_state_index(self.es_s32_j, 1), 4096) self.assertEqual(hs.basis_state_index(self.es_s32_j, 2), 8192) self.assertEqual(hs.basis_state_index(self.es_s32_j, 3), 12288)
def test_constructors(self): hs_empty = HilbertSpace() self.assertEqual(len(hs_empty), 0) self.assertEqual(hs_empty.total_n_bits, 0) self.assertEqual(hs_empty.dim, 1) hs1 = HilbertSpace([ self.es_s32_i, self.es_s32_j, self.es_s1_i, self.es_s1_j, self.es_s_i, self.es_s_j, self.es_b_x, self.es_b_y, self.es_f_dn, self.es_f_up ]) self.assertEqual(len(hs1), 10) self.assertEqual(hs1.total_n_bits, 20) self.assertEqual(hs1.dim, 1048576) with self.assertRaisesRegex(RuntimeError, "^Elementary space already exists$"): HilbertSpace( [self.es_s32_i, self.es_s_i, self.es_s_i, self.es_f_dn]) self.assertEqual(HilbertSpace(self.fermion_es), HilbertSpace([self.es_f_dn, self.es_f_up])) self.assertEqual(HilbertSpace(self.boson_es), HilbertSpace([self.es_b_x, self.es_b_y])) self.assertEqual(HilbertSpace(self.spin_es), HilbertSpace([self.es_s_i, self.es_s_j])) self.assertEqual(HilbertSpace(self.spin1_es), HilbertSpace([self.es_s1_i, self.es_s1_j])) self.assertEqual(HilbertSpace(self.spin32_es), HilbertSpace([self.es_s32_i, self.es_s32_j]))
omega = np.array([0.8]) # Qubit-oscillator coupling constants as a 2x1 array. g = np.array([[0.5], [0.6]]) # Create the Tavis-Cummings Hamiltonian. H = jaynes_cummings(eps, omega, g) # Construct state space of our problem as a direct product of two # two-dimensional Hilbert spaces (qubits) and one truncated bosonic Hilbert # space. # make_space_boson(4) returns the truncated bosonic space with allowed # occupation numbers N = 0, 1, ..., (2^4-1). hs = HilbertSpace([ make_space_spin(1 / 2, 0), # Qubit 1: spin-1/2, index 0 make_space_spin(1 / 2, 1), # Qubit 2: spin-1/2, index 1 make_space_boson(4, 0) # Oscillator, index 0 ]) # Construct a linear operator corresponding to 'H' and acting in the Hilbert # space 'hs'. H_op = LOperatorR(H, hs) # # Prepare a matrix representation of 'H_op' # # Method I (manual). H_mat1 = np.zeros((hs.dim, hs.dim)) for i in range(hs.dim): # A column vector psi = {0, 0, ..., 1, ..., 0}
def test_from_expression(self): expr = 2.0 * S_p("i", 0, spin=3 / 2) * S_m("j", 0, spin=3 / 2) \ + 5.0 * n("up", 0) * n("dn", 0) hs1 = HilbertSpace(expr) self.assertEqual(len(hs1), 4) self.assertEqual(hs1.total_n_bits, 6) self.assertEqual(hs1.dim, 64) self.assertTrue(self.es_f_dn in hs1) self.assertEqual(hs1.index(self.es_f_dn), 0) self.assertEqual(hs1.bit_range(self.es_f_dn), (0, 0)) self.assertTrue(self.es_f_up in hs1) self.assertEqual(hs1.index(self.es_f_up), 1) self.assertEqual(hs1.bit_range(self.es_f_up), (1, 1)) self.assertTrue(self.es_s32_i in hs1) self.assertEqual(hs1.index(self.es_s32_i), 2) self.assertEqual(hs1.bit_range(self.es_s32_i), (2, 3)) self.assertTrue(self.es_s32_j in hs1) self.assertEqual(hs1.index(self.es_s32_j), 3) self.assertEqual(hs1.bit_range(self.es_s32_j), (4, 5)) # foreach() count = 0 def counter(i): nonlocal count count += i foreach(hs1, counter) self.assertEqual(count, 2016) expr += a_dag("x", 0) + a("y", 0) hs2 = HilbertSpace(expr, bits_per_boson=4) self.assertEqual(len(hs2), 6) self.assertEqual(hs2.total_n_bits, 14) self.assertEqual(hs2.dim, 16384) self.assertTrue(self.es_f_dn in hs2) self.assertEqual(hs2.index(self.es_f_dn), 0) self.assertEqual(hs2.bit_range(self.es_f_dn), (0, 0)) self.assertTrue(self.es_f_up in hs2) self.assertEqual(hs2.index(self.es_f_up), 1) self.assertEqual(hs2.bit_range(self.es_f_up), (1, 1)) self.assertTrue(self.es_b_x in hs2) self.assertEqual(hs2.index(self.es_b_x), 2) self.assertEqual(hs2.bit_range(self.es_b_x), (2, 5)) self.assertTrue(self.es_b_y in hs2) self.assertEqual(hs2.index(self.es_b_y), 3) self.assertEqual(hs2.bit_range(self.es_b_y), (6, 9)) self.assertTrue(self.es_s32_i in hs2) self.assertEqual(hs2.index(self.es_s32_i), 4) self.assertEqual(hs2.bit_range(self.es_s32_i), (10, 11)) self.assertTrue(self.es_s32_j in hs2) self.assertEqual(hs2.index(self.es_s32_j), 5) self.assertEqual(hs2.bit_range(self.es_s32_j), (12, 13))
def test_add(self): hs = HilbertSpace([self.es_s32_i]) def check_hs(es, index, size, total_n_bits, b, e, fermion, boson, spin): self.assertEqual(len(hs), size) self.assertEqual(hs.total_n_bits, total_n_bits) self.assertEqual(hs.dim, 1 << total_n_bits) self.assertTrue(es in hs) self.assertEqual(hs.index(es), index) self.assertEqual(hs.bit_range(es), (b, e)) if fermion is not None: self.assertTrue(hs.has_algebra(FERMION)) self.assertEqual(hs.algebra_bit_range(FERMION), fermion) else: self.assertFalse(hs.has_algebra(FERMION)) with self.assertRaisesRegex( RuntimeError, "^No elementary spaces with algebra ID %i$" % FERMION): hs.algebra_bit_range(FERMION) if boson is not None: self.assertTrue(hs.has_algebra(BOSON)) self.assertEqual(hs.algebra_bit_range(BOSON), boson) else: self.assertFalse(hs.has_algebra(BOSON)) with self.assertRaisesRegex( RuntimeError, "^No elementary spaces with algebra ID %i$" % BOSON): hs.algebra_bit_range(BOSON) if spin is not None: self.assertTrue(hs.has_algebra(SPIN)) self.assertEqual(hs.algebra_bit_range(SPIN), spin) else: self.assertFalse(hs.has_algebra(SPIN)) with self.assertRaisesRegex( RuntimeError, "^No elementary spaces with algebra ID %i$" % SPIN): hs.algebra_bit_range(SPIN) check_hs(self.es_s32_i, 0, 1, 2, 0, 1, None, None, (0, 1)) hs.add(self.es_s32_j) check_hs(self.es_s32_j, 1, 2, 4, 2, 3, None, None, (0, 3)) hs.add(self.es_s1_j) check_hs(self.es_s1_j, 0, 3, 6, 0, 1, None, None, (0, 5)) hs.add(self.es_s_i) check_hs(self.es_s_i, 0, 4, 7, 0, 0, None, None, (0, 6)) hs.add(self.es_s_j) check_hs(self.es_s_j, 1, 5, 8, 1, 1, None, None, (0, 7)) hs.add(self.es_b_x) check_hs(self.es_b_x, 0, 6, 12, 0, 3, None, (0, 3), (4, 11)) hs.add(self.es_f_dn) check_hs(self.es_f_dn, 0, 7, 13, 0, 0, (0, 0), (1, 4), (5, 12)) hs.add(self.es_f_up) check_hs(self.es_f_up, 1, 8, 14, 1, 1, (0, 1), (2, 5), (6, 13)) with self.assertRaisesRegex(RuntimeError, "^Elementary space already exists$"): hs.add(self.es_s_j) check_hs(self.es_f_dn, 0, 8, 14, 0, 0, (0, 1), (2, 5), (6, 13)) check_hs(self.es_f_up, 1, 8, 14, 1, 1, (0, 1), (2, 5), (6, 13)) check_hs(self.es_b_x, 2, 8, 14, 2, 5, (0, 1), (2, 5), (6, 13)) check_hs(self.es_s_i, 3, 8, 14, 6, 6, (0, 1), (2, 5), (6, 13)) check_hs(self.es_s_j, 4, 8, 14, 7, 7, (0, 1), (2, 5), (6, 13)) check_hs(self.es_s1_j, 5, 8, 14, 8, 9, (0, 1), (2, 5), (6, 13)) check_hs(self.es_s32_i, 6, 8, 14, 10, 11, (0, 1), (2, 5), (6, 13)) check_hs(self.es_s32_j, 7, 8, 14, 12, 13, (0, 1), (2, 5), (6, 13)) self.assertEqual(hs.algebra_bit_range(FERMION), (0, 1)) self.assertEqual(hs.algebra_bit_range(BOSON), (2, 5)) self.assertEqual(hs.algebra_bit_range(SPIN), (6, 13))
def test_n_fermion_multisector_size(self): hs = HilbertSpace() # # Empty Hilbert space # self.assertEqual(n_fermion_multisector_size(hs, []), 0) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(1)): n_fermion_multisector_size(hs, [self.sda(1)]) # # Empty sectors # self.assertEqual(n_fermion_multisector_size(hs, [self.sde(0)]), 0) self.assertEqual(n_fermion_multisector_size(hs, [self.sde(1)]), 0) self.assertEqual( n_fermion_multisector_size(hs, [self.sde(0), self.sde(0)]), 0) self.assertEqual( n_fermion_multisector_size(hs, [self.sde(1), self.sde(1)]), 0) # # Purely fermionic Hilbert spaces # for i in range(self.M_total): hs.add(make_space_fermion(i)) # Empty sectors self.assertEqual(n_fermion_multisector_size(hs, [self.sde(0)]), 2048) self.assertEqual(n_fermion_multisector_size(hs, [self.sde(1)]), 0) self.assertEqual( n_fermion_multisector_size(hs, [self.sde(0), self.sde(0)]), 2048) self.assertEqual( n_fermion_multisector_size(hs, [self.sde(1), self.sde(1)]), 0) with self.assertRaisesRegex(RuntimeError, "^Some of the sectors overlap$"): n_fermion_multisector_size(hs, [self.sda(2), ([(6, )], 1)]) self.assertEqual(n_fermion_multisector_size(hs, []), 2048) # One sector for N in range(self.Na_max + 1): self.assertEqual(n_fermion_multisector_size(hs, [self.sda(N)]), self.ab_size_ref[N] * 128) for N in range(self.N5_max + 1): self.assertEqual(n_fermion_multisector_size(hs, [self.sd5(N)]), 1024) for N in range(self.Nb_max + 1): self.assertEqual(n_fermion_multisector_size(hs, [self.sdb(N)]), self.ab_size_ref[N] * 128) # Two sectors for N1, N2 in product(range(self.Na_max + 1), range(self.Nb_max + 1)): self.assertEqual( n_fermion_multisector_size( hs, [self.sda(N1), self.sdb(N2)]), self.ab_size_ref[N1] * self.ab_size_ref[N2] * 8) # Three sectors for N1, N2, N3 in product(range(self.Na_max + 1), range(self.N5_max + 1), range(self.Nb_max + 1)): self.assertEqual( n_fermion_multisector_size( hs, [self.sda(N1), self.sd5(N2), self.sdb(N3)]), self.ab_size_ref[N1] * self.ab_size_ref[N3] * 4) # Mixture with the empty sector for N in range(self.Na_max + 1): self.assertEqual( n_fermion_multisector_size( hs, [self.sda(N), self.sde(0)]), self.ab_size_ref[N] * 128) for N in range(self.N5_max + 1): self.assertEqual( n_fermion_multisector_size( hs, [self.sd5(N), self.sde(0)]), 1024) for N in range(self.Nb_max + 1): self.assertEqual( n_fermion_multisector_size( hs, [self.sdb(N), self.sde(0)]), self.ab_size_ref[N] * 128) # # Fermions and bosons # hs.add(make_space_boson(2, 0)) self.assertEqual(n_fermion_multisector_size(hs, []), 8192) # One sector for N in range(self.Na_max + 1): self.assertEqual(n_fermion_multisector_size(hs, [self.sda(N)]), self.ab_size_ref[N] * 512) for N in range(self.N5_max + 1): self.assertEqual(n_fermion_multisector_size(hs, [self.sd5(N)]), 4096) for N in range(self.Nb_max + 1): self.assertEqual(n_fermion_multisector_size(hs, [self.sdb(N)]), self.ab_size_ref[N] * 512) # Two sectors for N1, N2 in product(range(self.Na_max + 1), range(self.Nb_max + 1)): self.assertEqual( n_fermion_multisector_size( hs, [self.sda(N1), self.sdb(N2)]), self.ab_size_ref[N1] * self.ab_size_ref[N2] * 32) # Three sectors for N1, N2, N3 in product(range(self.Na_max + 1), range(self.N5_max + 1), range(self.Nb_max + 1)): self.assertEqual( n_fermion_multisector_size( hs, [self.sda(N1), self.sd5(N2), self.sdb(N3)]), self.ab_size_ref[N1] * self.ab_size_ref[N3] * 16) # Mixture with the empty sector for N in range(self.Na_max + 1): self.assertEqual( n_fermion_multisector_size( hs, [self.sda(N), self.sde(0)]), self.ab_size_ref[N] * 512) for N in range(self.N5_max + 1): self.assertEqual( n_fermion_multisector_size( hs, [self.sd5(N), self.sde(0)]), 4096) for N in range(self.Nb_max + 1): self.assertEqual( n_fermion_multisector_size( hs, [self.sdb(N), self.sde(0)]), self.ab_size_ref[N] * 512) # # Purely bosonic Hilbert space # hs_b = HilbertSpace([make_space_boson(2, 0), make_space_boson(3, 1)]) self.assertEqual(n_fermion_multisector_size(hs_b, []), 32) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(1)): n_fermion_multisector_size(hs_b, [self.sda(1)])
def test_loperator(self): hs = HilbertSpace([make_space_boson(2, 0)]) for i in range(self.M_total): hs.add(make_space_fermion(i)) sector_a_modes = [1, 2, 6, 7] sector_b_modes = [3, 4, 8, 9] Ha = (n(1) + n(2) + n(6) + n(7)) * (a_dag(0) + a(0)) Hb = (n(3) + n(4) + n(8) + n(9)) * (a_dag(0) + a(0)) for src_type, dst_type, lop_type in [(float, float, LOperatorR), (float, complex, LOperatorR), (complex, complex, LOperatorR), (float, complex, LOperatorC), (complex, complex, LOperatorC)]: src_view_type = NFermionMultiSectorViewR if (src_type == float) \ else NFermionMultiSectorViewC dst_view_type = NFermionMultiSectorViewR if (dst_type == float) \ else NFermionMultiSectorViewC lop_is_real = lop_type == LOperatorR Hopa = lop_type(Ha if lop_is_real else make_complex(Ha), hs) Hopb = lop_type(Hb if lop_is_real else make_complex(Hb), hs) for N1, N2 in product(range(self.Na_max + 1), range(self.Nb_max + 1)): sectors = [self.sda(N1), self.sdb(N2)] src = np.zeros(n_fermion_multisector_size(hs, sectors), dtype=src_type) view_src = src_view_type(src, hs, sectors) dst = np.zeros(n_fermion_multisector_size(hs, sectors), dtype=dst_type) view_dst = dst_view_type(dst, hs, sectors) # Input: # First N1 modes of sector A are occupied # First N2 modes of sector B are occupied # 1 boson index_in_f = sum(2**sector_a_modes[n1] for n1 in range(N1)) index_in_f += sum(2**sector_b_modes[n2] for n2 in range(N2)) src[view_src.map_index(index_in_f + (2**self.M_total))] = 1 Hopa(view_src, view_dst) ref = np.zeros(n_fermion_multisector_size(hs, sectors), dtype=dst_type) # 0 bosons ref[view_dst.map_index(index_in_f)] = N1 # 2 bosons ref[view_dst.map_index(index_in_f + (2 ** (self.M_total + 1)))]\ = N1 * np.sqrt(2) assert_allclose(dst, ref) Hopb(view_src, view_dst) ref = np.zeros(n_fermion_multisector_size(hs, sectors), dtype=dst_type) # 0 bosons ref[view_dst.map_index(index_in_f)] = N2 # 2 bosons ref[view_dst.map_index(index_in_f + (2 ** (self.M_total + 1)))]\ = N2 * np.sqrt(2) assert_allclose(dst, ref)
def test_n_fermion_sector_basis_states(self): st = np.array([], dtype=float) # Build a reference list of basis states for # n_fermion_multisector_basis_states() by repeatedly calling map_index() def build_basis_states_ref(hs, sectors, selector): view = NFermionMultiSectorViewR(st, hs, sectors) basis_states = [-1] * n_fermion_multisector_size(hs, sectors) for index in range(hs.dim): if selector(index): basis_states[view.map_index(index)] = index return basis_states hs = HilbertSpace() # # Empty Hilbert space # self.assertEqual(n_fermion_multisector_basis_states(hs, []), []) self.assertEqual(n_fermion_multisector_basis_states(hs, [self.sde(0)]), []) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_multisector_basis_states(hs, [self.sde(1)]) self.assertEqual( n_fermion_multisector_basis_states( hs, [self.sde(0), self.sde(0)]), []) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_multisector_basis_states(hs, [self.sde(0), self.sde(1)]) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_multisector_basis_states(hs, [self.sde(1), self.sde(0)]) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_multisector_basis_states(hs, [self.sde(1), self.sde(1)]) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(0)): n_fermion_multisector_basis_states(hs, [self.sd0(0)]) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(0)): n_fermion_multisector_basis_states(hs, [self.sd0(1)]) # # Purely fermionic Hilbert spaces # for i in range(self.M_total): hs.add(make_space_fermion(i)) for N in range(self.N5_max + 1): sectors = [self.sd5(N)] ref = build_basis_states_ref(hs, sectors, self.sd5_index_selector(N)) self.assertEqual(n_fermion_multisector_basis_states(hs, sectors), ref) for N1, N2 in product(range(self.Na_max + 1), range(self.Nb_max + 1)): sectors = [self.sda(N1), self.sdb(N2)] ref = build_basis_states_ref(hs, sectors, self.sdab_index_selector(N1, N2)) self.assertEqual(n_fermion_multisector_basis_states(hs, sectors), ref) for N1, N2, N3 in product(range(self.Na_max + 1), range(self.N5_max + 1), range(self.Nb_max + 1)): sectors = [self.sda(N1), self.sd5(N2), self.sdb(N3)] ref = build_basis_states_ref(hs, sectors, self.sda5b_index_selector(N1, N2, N3)) self.assertEqual(n_fermion_multisector_basis_states(hs, sectors), ref) # # Fermions and bosons # hs.add(make_space_boson(2, self.M_total)) hs.add(make_space_boson(2, self.M_total + 1)) for N in range(self.N5_max + 1): sectors = [self.sd5(N)] ref = build_basis_states_ref(hs, sectors, self.sd5_index_selector(N)) self.assertEqual(n_fermion_multisector_basis_states(hs, sectors), ref) for N1, N2 in product(range(self.Na_max + 1), range(self.Nb_max + 1)): sectors = [self.sda(N1), self.sdb(N2)] ref = build_basis_states_ref(hs, sectors, self.sdab_index_selector(N1, N2)) self.assertEqual(n_fermion_multisector_basis_states(hs, sectors), ref) for N1, N2, N3 in product(range(self.Na_max + 1), range(self.N5_max + 1), range(self.Nb_max + 1)): sectors = [self.sda(N1), self.sd5(N2), self.sdb(N3)] ref = build_basis_states_ref(hs, sectors, self.sda5b_index_selector(N1, N2, N3)) self.assertEqual(n_fermion_multisector_basis_states(hs, sectors), ref) # # Purely bosonic Hilbert space # hs_b = HilbertSpace([make_space_boson(2, 0), make_space_boson(3, 1)]) ref = list(range(n_fermion_multisector_size(hs_b, []))) self.assertEqual(n_fermion_multisector_basis_states(hs_b, []), ref) self.assertEqual( n_fermion_multisector_basis_states(hs_b, [self.sde(0)]), ref) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_multisector_basis_states(hs_b, [self.sde(1)]) self.assertEqual( n_fermion_multisector_basis_states( hs_b, [self.sde(0), self.sde(0)]), ref) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_multisector_basis_states( hs_b, [self.sde(0), self.sde(1)]) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_multisector_basis_states( hs_b, [self.sde(1), self.sde(0)]) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(0, 1)): n_fermion_multisector_basis_states( hs_b, [self.sde(1), self.sde(1)]) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(0)): n_fermion_multisector_basis_states(hs_b, [self.sd0(0)]) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(0)): n_fermion_multisector_basis_states(hs_b, [self.sd0(1)])
def test_init_exceptions(self): st = np.array([], dtype=float) hs = HilbertSpace() # # Empty Hilbert space # for ViewType in (NFermionMultiSectorViewR, NFermionMultiSectorViewC): with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(1)): ViewType(st, hs, [self.sda(0)]) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(1)): ViewType(st, hs, [self.sda(1)]) # # One fermion # hs.add(make_space_fermion(0)) for ViewType in (NFermionMultiSectorViewR, NFermionMultiSectorViewC): with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(1, 2)): ViewType(st, hs, [self.sd0(2)]) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(1)): ViewType(st, hs, [self.sda(0)]) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(1)): ViewType(st, hs, [self.sda(1)]) # # Multiple fermions # for i in range(1, self.M_total): hs.add(make_space_fermion(i)) for ViewType in (NFermionMultiSectorViewR, NFermionMultiSectorViewC): for N in range(self.Na_max): with self.assertRaisesRegex(RuntimeError, "^Some of the sectors overlap$"): ViewType(st, hs, [self.sda(N), self.sda(N)]) with self.assertRaisesRegex(RuntimeError, "^Some of the sectors overlap$"): ViewType(st, hs, [self.sde(0), self.sda(N), self.sda(N)]) with self.assertRaisesRegex(RuntimeError, "^Some of the sectors overlap$"): ViewType(st, hs, [self.sda(N), self.sde(0), self.sda(N)]) with self.assertRaisesRegex(RuntimeError, "^Some of the sectors overlap$"): ViewType(st, hs, [self.sda(N), self.sda(N), self.sde(0)]) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(1, 2)): ViewType(st, hs, [self.sd0(2)]) # # Fermions and bosons # hs.add(make_space_boson(1, 5)) hs.add(make_space_boson(2, 6)) for ViewType in (NFermionMultiSectorViewR, NFermionMultiSectorViewC): for N in range(self.Na_max): with self.assertRaisesRegex(RuntimeError, "^Some of the sectors overlap$"): ViewType(st, hs, [self.sda(N), self.sda(N)]) with self.assertRaisesRegex(RuntimeError, "^Some of the sectors overlap$"): ViewType(st, hs, [self.sde(0), self.sda(N), self.sda(N)]) with self.assertRaisesRegex(RuntimeError, "^Some of the sectors overlap$"): ViewType(st, hs, [self.sda(N), self.sde(0), self.sda(N)]) with self.assertRaisesRegex(RuntimeError, "^Some of the sectors overlap$"): ViewType(st, hs, [self.sda(N), self.sda(N), self.sde(0)]) with self.assertRaisesRegex(RuntimeError, self.wrong_n_error_msg(1, 2)): ViewType(st, hs, [self.sd0(2)]) # # Purely bosonic Hilbert space # hs_b = HilbertSpace([make_space_boson(2, 0), make_space_boson(3, 1)]) for ViewType in (NFermionMultiSectorViewR, NFermionMultiSectorViewC): with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(0)): ViewType(st, hs_b, [self.sd0(0)]) with self.assertRaisesRegex(RuntimeError, self.wrong_indices_error_msg(0)): ViewType(st, hs_b, [self.sd0(1)])