def test_4_spins(): # fmt: off matrix = np.array([[1, 0, 0, 0], [0, -1, 2, 0], [0, 2, -1, 0], [0, 0, 0, 1]]) # fmt: on number_spins = 4 edges = [(i, (i + 1) % number_spins) for i in range(number_spins)] basis = ls.SpinBasis(ls.Group([]), number_spins=4, hamming_weight=2) basis.build() assert basis.number_states == 6 operator = ls.Operator(basis, [ls.Interaction(matrix, edges)]) assert np.isclose(ls.diagonalize(operator, k=1)[0], -8) basis = ls.SpinBasis(ls.Group([]), number_spins=4, hamming_weight=2, spin_inversion=1) basis.build() assert basis.number_states == 3 operator = ls.Operator(basis, [ls.Interaction(matrix, edges)]) assert np.isclose(ls.diagonalize(operator, k=1)[0], -8) T = ls.Symmetry([1, 2, 3, 0], sector=0) basis = ls.SpinBasis(ls.Group([T]), number_spins=4, hamming_weight=2, spin_inversion=1) basis.build() assert basis.number_states == 2 operator = ls.Operator(basis, [ls.Interaction(matrix, edges)]) assert np.isclose(ls.diagonalize(operator, k=1)[0], -8)
def main(): number_spins = 10 # System size hamming_weight = number_spins // 2 # Hamming weight (i.e. number of spin ups) # Constructing symmetries symmetries = [] sites = np.arange(number_spins) # Momentum in x direction with eigenvalue π T = (sites + 1) % number_spins symmetries.append(ls.Symmetry(T, sector=number_spins // 2)) # Parity with eigenvalue π P = sites[::-1] symmetries.append(ls.Symmetry(P, sector=1)) # Constructing the group symmetry_group = ls.Group(symmetries) print("Symmetry group contains {} elements".format(len(symmetry_group))) # Constructing the basis basis = ls.SpinBasis( symmetry_group, number_spins=number_spins, hamming_weight=hamming_weight, spin_inversion=-1 ) basis.build() # Build the list of representatives, we need it since we're doing ED print("Hilbert space dimension is {}".format(basis.number_states)) # Heisenberg Hamiltonian # fmt: off σ_x = np.array([ [0, 1] , [1, 0] ]) σ_y = np.array([ [0 , -1j] , [1j, 0] ]) σ_z = np.array([ [1, 0] , [0, -1] ]) # fmt: on σ_p = σ_x + 1j * σ_y σ_m = σ_x - 1j * σ_y matrix = 0.5 * (np.kron(σ_p, σ_m) + np.kron(σ_m, σ_p)) + np.kron(σ_z, σ_z) edges = [(i, (i + 1) % number_spins) for i in range(number_spins)] hamiltonian = ls.Operator(basis, [ls.Interaction(matrix, edges)]) # Diagonalize the Hamiltonian using ARPACK eigenvalues, eigenstates = ls.diagonalize(hamiltonian, k=1) print("Ground state energy is {:.10f}".format(eigenvalues[0])) assert np.isclose(eigenvalues[0], -18.06178542)
def test_cast_to_basis(): T = ls.Symmetry([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], sector=5) P = ls.Symmetry([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], sector=1) basis1 = ls.SpinBasis(ls.Group([T]), number_spins=10, hamming_weight=5, spin_inversion=-1) basis1.build() matrix = np.array([[1, 0, 0, 0], [0, -1, 2, 0], [0, 2, -1, 0], [0, 0, 0, 1]]) edges = [(i, (i + 1) % basis1.number_spins) for i in range(basis1.number_spins)] operator1 = ls.Operator(basis1, [ls.Interaction(matrix, edges)]) E1, x1 = ls.diagonalize(operator1) x1 = x1.squeeze() basis2 = ls.SpinBasis(ls.Group([P]), number_spins=10, hamming_weight=5) basis2.build() operator2 = ls.Operator(basis2, [ls.Interaction(matrix, edges)]) E2, x2 = ls.diagonalize(operator2) x2 = x2.squeeze() assert np.isclose(E1, E2) y = reference_cast_to_basis(basis1, basis2, x2) y2 = cast_to_basis(basis1, basis2, x2) assert np.allclose(y, y2) assert np.isclose(np.abs(np.dot(x1, y)), 1.0)
def test_state_info_flat_basis(): basis = ls.SpinBasis(ls.Group( [ls.Symmetry(list(range(1, 20)) + [0], sector=1)]), number_spins=20) basis.build() flat = ls.FlatSpinBasis(basis) full = ls.SpinBasis(ls.Group([]), number_spins=20) full.build() r1, e1, n1 = basis.batched_state_info( np.hstack((full.states.reshape(-1, 1), np.zeros((full.number_states, 7), dtype=np.uint64)))) r2, e2, n2 = flat.state_info(full.states) assert np.all(r1[:, 0] == r2) assert np.all(n1 == n2) assert np.all(e1 == e2) is_r2, n2 = flat.is_representative(full.states) assert np.all(basis.states == full.states[is_r2.view(np.bool_)])
def make_basis(L_x, L_y, sectors=dict()): assert L_x > 0 and L_y > 0 sites = np.arange(L_y * L_x, dtype=np.int32) x = sites % L_x y = sites // L_x symmetries = [] if L_x > 1: T_x = (x + 1) % L_x + L_x * y # translation along x-direction symmetries.append(("T_x", T_x, sectors.get("T_x", 0))) P_x = (L_x - 1 - x) + L_x * y # reflection over y-axis symmetries.append(("P_x", P_x, sectors.get("P_x", 0))) if L_y > 1: T_y = x + L_x * ((y + 1) % L_y) # translation along y-direction symmetries.append(("T_y", T_y, sectors.get("T_y", 0))) P_y = x + L_x * (L_y - 1 - y) # reflection around x-axis symmetries.append(("P_y", P_y, sectors.get("P_y", 0))) if L_x == L_y and L_x > 1: # Rotations are valid only for square samples R = np.rot90(sites.reshape(L_y, L_x), k=-1).reshape(-1) symmetries.append(("R", R, sectors.get("R", 0))) if L_x * L_y % 2 == 0: symmetries.append(("I", None, sectors.get("I", 0))) hamming_weight = (L_x * L_y) // 2 spin_inversion = None processed_symmetries = [] for s in symmetries: _, x1, x2 = s if x1 is None: assert x2 == 0 or x2 == 1 spin_inversion = 1 if x2 == 0 else -1 else: processed_symmetries.append(ls.Symmetry(x1, sector=x2)) group = ls.Group(processed_symmetries) basis = ls.SpinBasis( group, number_spins=L_x * L_y, hamming_weight=hamming_weight, spin_inversion=spin_inversion, ) basis.build() return basis
def test_construct_flat_basis(): basis = ls.SpinBasis(ls.Group([]), number_spins=4, hamming_weight=2) flat_basis = ls.FlatSpinBasis(basis) assert flat_basis.number_spins == 4 assert flat_basis.hamming_weight == 2 assert flat_basis.spin_inversion is None basis = ls.SpinBasis(ls.Group([ls.Symmetry([1, 2, 3, 0], sector=1)]), number_spins=4, hamming_weight=2) flat_basis = ls.FlatSpinBasis(basis) assert flat_basis.number_spins == 4 assert flat_basis.hamming_weight == 2 assert flat_basis.spin_inversion is None # print(flat_basis.serialize()) buf = flat_basis.serialize() other_basis = ls.FlatSpinBasis.deserialize(buf) assert other_basis.number_spins == 4 assert other_basis.hamming_weight == 2 assert other_basis.spin_inversion is None assert np.all(other_basis.serialize() == buf)
def test_2_spins(): basis = ls.SpinBasis(ls.Group([]), number_spins=2) basis.build() assert basis.states.tolist() == [0, 1, 2, 3] with pytest.raises(ls.LatticeSymmetriesException): ls.SpinBasis(ls.Group([]), number_spins=2, hamming_weight=2, spin_inversion=1) with pytest.raises(ls.LatticeSymmetriesException): ls.SpinBasis(ls.Group([]), number_spins=2, hamming_weight=2, spin_inversion=-1) basis = ls.SpinBasis(ls.Group([ls.Symmetry([1, 0], sector=1)]), number_spins=2) basis.build() assert basis.states.tolist() == [1] assert basis.state_info(0) == (0, 1.0, 0.0) assert basis.state_info(1) == (1, 1.0, pytest.approx(1 / math.sqrt(2))) assert basis.state_info(2) == (1, -1.0, pytest.approx(1 / math.sqrt(2))) assert basis.state_info(3) == (3, 1.0, 0.0)
def _ls_make_basis(symmetries, number_spins, hamming_weight=None, build=True): spin_inversion = None processed_symmetries = [] for s in symmetries: _, x1, x2 = s if x1 is None: assert x2 == 0 or x2 == 1 spin_inversion = 1 if x2 == 0 else -1 else: processed_symmetries.append(ls.Symmetry(x1, sector=x2)) group = ls.Group(processed_symmetries) logger.info("Symmetry group contains {} elements", len(group)) basis = ls.SpinBasis( group, number_spins=number_spins, hamming_weight=hamming_weight, spin_inversion=spin_inversion, ) if build: basis.build() return basis