Exemplo n.º 1
0
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)
Exemplo n.º 2
0
def test_1_spin():
    basis = ls.SpinBasis(ls.Group([]), number_spins=1)
    basis.build()
    assert basis.states.tolist() == [0, 1]
    assert basis.state_info(0) == (0, 1.0, 1.0)
    assert basis.state_info(1) == (1, 1.0, 1.0)
    basis = ls.SpinBasis(ls.Group([]), number_spins=1, hamming_weight=0)
    basis.build()
    assert basis.states.tolist() == [0]
    assert basis.state_info(0) == (0, 1.0, 1.0)
    basis = ls.SpinBasis(ls.Group([]), number_spins=1, spin_inversion=-1)
    basis.build()
    assert basis.states.tolist() == [0]
    assert basis.state_info(0) == (0, 1.0, pytest.approx(1 / math.sqrt(2)))
    assert basis.state_info(1) == (0, -1.0, pytest.approx(1 / math.sqrt(2)))
def test_non_hermitian_matvec():
    basis = ls.SpinBasis(ls.Group([]), number_spins=2)
    basis.build()

    rng = np.random.default_rng()
    matrix = rng.random((4, 4)) + rng.random((4, 4)) * 1j - (0.5 + 0.5j)
    operator = ls.Operator(basis, [ls.Interaction(matrix, [(0, 1)])])

    # print(operator.to_csr().toarray())
    # print(matrix[[0, 2, 1, 3], :][:, [0, 2, 1, 3]])
    assert np.all(
        operator.to_csr().toarray() == matrix[[0, 2, 1, 3], :][:,
                                                               [0, 2, 1, 3]])

    for (i, spin) in enumerate(basis.states):
        v = np.zeros(basis.number_states, dtype=np.complex128)
        v[i] = 1.0
        predicted = operator(v)
        expected = matrix[[0, 2, 1, 3], :][:, [0, 2, 1, 3]] @ v
        # print(predicted, expected)
        assert np.allclose(predicted, expected)

    v = rng.random(4) + rng.random(4) * 1j - (0.5 + 0.5j)
    predicted = operator(v)
    expected = matrix[[0, 2, 1, 3], :][:, [0, 2, 1, 3]] @ v
    # print(predicted)
    # print(expected)
    assert np.allclose(predicted, expected)
Exemplo n.º 4
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_)])
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
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 test_index():
    basis = ls.SpinBasis(ls.Group([]), number_spins=4, hamming_weight=2)
    basis.build()

    states = basis.states
    print(states)
    print(ls.batched_index(basis, states))
    # print(ls.batched_index(basis, np.array([3, 9, 10, 12, 8], dtype=np.uint64)))
    # for i in range(len(states)):
    #     assert i == ls._numba_index(basis._payload.value, states[i])

    bits = np.zeros((len(states), 8), dtype=np.uint64)
    bits[:, 0] = states
    print(ls.batched_state_info(basis, bits))
    print(basis.state_info(states[1]))
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)
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
def test_apply():
    basis = ls.SpinBasis(ls.Group([]), number_spins=10, hamming_weight=5)
    basis.build()
    # fmt: off
    matrix = np.array([[1, 0, 0, 0], [0, -1, 2, 0], [0, 2, -1, 0],
                       [0, 0, 0, 1]])
    # fmt: on
    edges = [(i, (i + 1) % basis.number_spins)
             for i in range(basis.number_spins)]
    operator = ls.Operator(basis, [ls.Interaction(matrix, edges)])

    for (i, spin) in enumerate(basis.states):
        spins, coeffs = operator.apply(spin)
        v = np.zeros(basis.number_states, dtype=np.float64)
        v[i] = 1.0
        v = operator(v)
        for (s, c) in zip(spins, coeffs):
            assert v[basis.index(s[0])] == c
Exemplo n.º 11
0
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
Exemplo n.º 12
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
Exemplo n.º 13
0
def test_batched_apply():
    basis = ls.SpinBasis(ls.Group([]), number_spins=10, hamming_weight=5)
    basis.build()
    # fmt: off
    matrix = np.array([[1, 0, 0, 0], [0, -1, 2, 0], [0, 2, -1, 0],
                       [0, 0, 0, 1]])
    # fmt: on
    edges = [(i, (i + 1) % basis.number_spins)
             for i in range(basis.number_spins)]
    operator = ls.Operator(basis, [ls.Interaction(matrix, edges)])

    for batch_size in [1, 2, 10, 20, 50]:
        x = basis.states[11:11 + batch_size]  # just a random range
        spins, coeffs, counts = operator.batched_apply(x)
        assert len(counts) == x.shape[0]
        offset = 0
        for i in range(batch_size):
            expected_spins, expected_coeffs = operator.apply(x[i])
            assert np.all(spins[offset:offset + counts[i]] == expected_spins)
            assert np.all(coeffs[offset:offset + counts[i]] == expected_coeffs)
            offset += counts[i]
        assert offset == spins.shape[0]
        assert offset == coeffs.shape[0]
Exemplo n.º 14
0
def test_huge():
    with pytest.raises(ls.LatticeSymmetriesException):
        ls.SpinBasis(ls.Group([]), number_spins=1000)
Exemplo n.º 15
0
def notest_construction():
    symmetries = [
        # ls.Symmetry([18, 19,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17], sector=5),
        # ls.Symmetry([19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1, 0], sector=0)
    ]
    basis = ls.SpinBasis(ls.Group(symmetries),
                         number_spins=20,
                         hamming_weight=10,
                         spin_inversion=None)
    basis.build()

    # fmt: off
    interactions = [
        ls.Interaction([[0.25, 0, 0, 0], [0, -0.25, 0.5, 0],
                        [0, 0.5, -0.25, 0.], [0., 0., 0., 0.25]],
                       [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11],
                        [12, 13], [14, 15], [16, 17], [18, 19]]),
        ls.Interaction(
            [[0.25, 0., 0., 0.], [0., -0.25, 0.5, 0.], [0., 0.5, -0.25, 0.],
             [0., 0., 0., 0.25]],
            [[0, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 7], [6, 8], [7, 9],
             [8, 10], [9, 11], [10, 12], [11, 13], [12, 14], [13, 15],
             [14, 16], [15, 17], [16, 18], [17, 19], [18, 0], [19, 1]]),
        ls.Interaction(
            [[-0.0625, -0., -0., -0.], [-0., 0.0625, -0.125, -0.],
             [-0., -0.125, 0.0625, -0.], [-0., -0., -0., -0.0625]],
            [[0, 4], [1, 5], [2, 6], [3, 7], [4, 8], [5, 9], [6, 10], [7, 11],
             [8, 12], [9, 13], [10, 14], [11, 15], [12, 16], [13, 17],
             [14, 18], [15, 19], [16, 0], [17, 1], [18, 2], [19, 3]]),
        ls.Interaction(
            [[0.02777778, 0., 0., 0.], [0., -0.02777778, 0.05555556, 0.],
             [0., 0.05555556, -0.02777778, 0.], [0., 0., 0., 0.02777778]],
            [[0, 6], [1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12],
             [7, 13], [8, 14], [9, 15], [10, 16], [11, 17], [12, 18], [13, 19],
             [14, 0], [15, 1], [16, 2], [17, 3], [18, 4], [19, 5]]),
        ls.Interaction(
            [[-0.015625, -0., -0., -0.], [-0., 0.015625, -0.03125, -0.],
             [-0., -0.03125, 0.015625, -0.], [-0., -0., -0., -0.015625]],
            [[0, 8], [1, 9], [2, 10], [3, 11], [4, 12], [5, 13], [6, 14],
             [7, 15], [8, 16], [9, 17], [10, 18], [11, 19], [12, 0], [13, 1],
             [14, 2], [15, 3], [16, 4], [17, 5], [18, 6], [19, 7]]),
        ls.Interaction(
            [[0.01, 0., 0., 0.], [0., -0.01, 0.02, 0.], [0., 0.02, -0.01, 0.],
             [0., 0., 0., 0.01]],
            [[0, 10], [1, 11], [2, 12], [3, 13], [4, 14], [5, 15], [6, 16],
             [7, 17], [8, 18], [9, 19], [10, 0], [11, 1], [12, 2], [13, 3],
             [14, 4], [15, 5], [16, 6], [17, 7], [18, 8], [19, 9]]),
        ls.Interaction(
            [[-0.00694444, -0., -0., -0.], [-0., 0.00694444, -0.01388889, -0.],
             [-0., -0.01388889, 0.00694444, -0.], [-0., -0., -0., -0.00694444]
             ], [[0, 12], [1, 13], [2, 14], [3, 15], [4, 16], [5, 17], [6, 18],
                 [7, 19], [8, 0], [9, 1], [10, 2], [11, 3], [12, 4], [13, 5],
                 [14, 6], [15, 7], [16, 8], [17, 9], [18, 10], [19, 11]]),
        ls.Interaction(
            [[0.00510204, 0., 0., 0.], [0., -0.00510204, 0.01020408, 0.],
             [0., 0.01020408, -0.00510204, 0.], [0., 0., 0., 0.00510204]],
            [[0, 14], [1, 15], [2, 16], [3, 17], [4, 18], [5, 19], [6, 0],
             [7, 1], [8, 2], [9, 3], [10, 4], [11, 5], [12, 6], [13, 7],
             [14, 8], [15, 9], [16, 10], [17, 11], [18, 12], [19, 13]]),
        ls.Interaction(
            [[-0.00390625, -0., -0., -0.], [-0., 0.00390625, -0.0078125, -0.],
             [-0., -0.0078125, 0.00390625, -0.], [-0., -0., -0., -0.00390625]],
            [[0, 16], [1, 17], [2, 18], [3, 19], [4, 0], [5, 1], [6, 2],
             [7, 3], [8, 4], [9, 5], [10, 6], [11, 7], [12, 8], [13, 9],
             [14, 10], [15, 11], [16, 12], [17, 13], [18, 14], [19, 15]]),
        ls.Interaction(
            [[0.00308642, 0., 0., 0.], [0., -0.00308642, 0.00617284, 0.],
             [0., 0.00617284, -0.00308642, 0.], [0., 0., 0., 0.00308642]],
            [[0, 18], [1, 19], [2, 0], [3, 1], [4, 2], [5, 3], [6, 4], [7, 5],
             [8, 6], [9, 7], [10, 8], [11, 9], [12, 10], [13, 11], [14, 12],
             [15, 13], [16, 14], [17, 15], [18, 16], [19, 17]])
    ]
    # fmt: on
    operator = ls.Operator(basis, interactions)

    e, _ = ls.diagonalize(operator, k=5)
    print(e)