예제 #1
0
def test_trotter_hamiltonian_operation_errors():
    """Test errors in ``TrotterHamiltonian`` addition and subtraction."""
    # test addition with different number of parts
    h1 = TFIM(nqubits=5, trotter=True)
    term = TFIM(nqubits=2, numpy=True)
    h2 = TrotterHamiltonian({
        (0, 1): term,
        (2, 3): term
    }, {
        (1, 2): term,
        (3, 4): term
    }, {(4, 0): term})
    with pytest.raises(ValueError):
        h = h1 + h2
    # test subtraction with incompatible parts
    h2 = TrotterHamiltonian({
        (0, 1): term,
        (2, 3): term
    }, {
        (1, 2): term,
        (3, 4): term
    })
    with pytest.raises(ValueError):
        h = h1 - h2
    # test matmul with bad type
    with pytest.raises(NotImplementedError):
        s = h1 @ "abc"
    # test matmul with bad shape
    with pytest.raises(ValueError):
        s = h1 @ np.zeros((2, 2))
예제 #2
0
def test_trotter_hamiltonian_make_compatible_repeating(nqubits):
    """Check ``make_compatible`` when first target is repeated in parts."""
    h0target = X(nqubits)
    h0 = X(nqubits, trotter=True)
    term = TFIM(2, numpy=True)
    parts = [{(0, i): term} for i in range(1, nqubits)]
    parts.extend(({(i, 0): term} for i in range(1, nqubits)))
    h1 = TrotterHamiltonian(*parts)

    h0c = h1.make_compatible(h0)
    assert not h1.is_compatible(h0)
    assert h1.is_compatible(h0c)
    np.testing.assert_allclose(h0c.matrix, h0target.matrix)
예제 #3
0
def test_trotter_hamiltonian_make_compatible_redundant():
    """Test ``make_compatible`` with redudant two-qubit terms."""
    h0 = X(2, trotter=True)
    target_matrix = h0.dense.matrix.numpy()
    target_matrix = np.kron(target_matrix, np.eye(2,
                                                  dtype=target_matrix.dtype))
    parts = [{(0, 1, 2): TFIM(3, numpy=True)}]
    h1 = TrotterHamiltonian(*parts)

    h0c = h1.make_compatible(h0)
    assert not h1.is_compatible(h0)
    assert h1.is_compatible(h0c)
    np.testing.assert_allclose(h0c.matrix, target_matrix)
예제 #4
0
def test_trotter_hamiltonian_make_compatible_simple():
    """Test ``make_compatible`` on a simple 3-qubit example."""
    h0target = X(3)
    h0 = X(3, trotter=True)
    term1 = Y(1, numpy=True)
    term2 = TFIM(2, numpy=True)
    parts = [{(0, 1): term2, (1, 2): term2, (0, 2): term2, (2, ): term1}]
    h1 = TrotterHamiltonian(*parts)

    h0c = h1.make_compatible(h0)
    assert not h1.is_compatible(h0)
    assert h1.is_compatible(h0c)
    np.testing.assert_allclose(h0c.matrix, h0target.matrix)
예제 #5
0
def test_from_symbolic_application_hamiltonian():
    """Check ``from_symbolic`` for a specific four-qubit Hamiltonian."""
    import sympy
    z1, z2, z3, z4 = sympy.symbols("z1 z2 z3 z4")
    symmap = {z: (i, matrices.Z) for i, z in enumerate([z1, z2, z3, z4])}
    symham = (z1 * z2 - 0.5 * z1 * z3 + 2 * z2 * z3 + 0.35 * z2 +
              0.25 * z3 * z4 + 0.5 * z3 + z4 - z1)
    # Check that Trotter dense matrix agrees will full Hamiltonian matrix
    fham = Hamiltonian.from_symbolic(symham, symmap)
    tham = TrotterHamiltonian.from_symbolic(symham, symmap)
    np.testing.assert_allclose(tham.dense.matrix, fham.matrix)
    # Check that no one-qubit terms exist in the Trotter Hamiltonian
    # (this means that merging was successful)
    first_targets = set()
    for part in tham.parts:
        for targets, term in part.items():
            first_targets.add(targets[0])
            assert len(targets) == 2
            assert term.nqubits == 2
    assert first_targets == set(range(4))
    # Check making an ``X`` Hamiltonian compatible with ``tham``
    xham = X(nqubits=4, trotter=True)
    cxham = tham.make_compatible(xham)
    assert not tham.is_compatible(xham)
    assert tham.is_compatible(cxham)
    np.testing.assert_allclose(xham.dense.matrix, cxham.dense.matrix)
예제 #6
0
def test_trotter_hamiltonian_initialization_errors():
    """Test errors in initialization of ``TrotterHamiltonian``."""
    # Wrong type of terms
    with pytest.raises(TypeError):
        ham = TrotterHamiltonian({(0, 1): "abc"})
    # Wrong type of parts
    with pytest.raises(TypeError):
        ham = TrotterHamiltonian([(0, 1)])
    # Wrong number of target qubits
    with pytest.raises(ValueError):
        ham = TrotterHamiltonian({(0, 1): TFIM(nqubits=3, numpy=True)})
    # Same targets multiple times
    h = TFIM(nqubits=2, numpy=True)
    with pytest.raises(ValueError):
        ham = TrotterHamiltonian({(0, 1): h}, {(0, 1): h})
    # Different term matrix types
    h2 = Hamiltonian(2, np.eye(4, dtype=np.float32), numpy=True)
    with pytest.raises(TypeError):
        ham = TrotterHamiltonian({(0, 1): h, (1, 2): h2})
    # ``from_twoqubit_term`` initialization with nqubits < 0
    with pytest.raises(ValueError):
        ham = TrotterHamiltonian.from_twoqubit_term(-2, h)
    # ``from_twoqubit_term`` initialization with more than 2 targets
    h = TFIM(nqubits=3, numpy=True)
    with pytest.raises(ValueError):
        ham = TrotterHamiltonian.from_twoqubit_term(4, h)
예제 #7
0
def test_trotter_hamiltonian_initialization_errors():
    """Test errors in initialization of ``TrotterHamiltonian``."""
    # Wrong type of terms
    with pytest.raises(TypeError):
        ham = TrotterHamiltonian({(0, 1): "abc"})
    # Wrong type of parts
    with pytest.raises(TypeError):
        ham = TrotterHamiltonian([(0, 1)])
    # Wrong number of target qubits
    with pytest.raises(ValueError):
        ham = TrotterHamiltonian({(0, 1): TFIM(nqubits=3, numpy=True)})
    # Same targets multiple times
    h = TFIM(nqubits=2, numpy=True)
    with pytest.raises(ValueError):
        ham = TrotterHamiltonian({(0, 1): h}, {(0, 1): h})
    # Different term Hamiltonian types
    h2 = TFIM(nqubits=2, numpy=False)
    with pytest.raises(TypeError):
        ham = TrotterHamiltonian({(0, 1): h, (1, 2): h2})
예제 #8
0
def test_trotter_hamiltonian_three_qubit_term(backend):
    """Test creating ``TrotterHamiltonian`` with three qubit term."""
    import qibo
    from scipy.linalg import expm
    original_backend = qibo.get_backend()
    qibo.set_backend(backend)
    m1 = utils.random_numpy_hermitian(3)
    m2 = utils.random_numpy_hermitian(2)
    m3 = utils.random_numpy_hermitian(1)

    term1 = Hamiltonian(3, m1, numpy=True)
    term2 = Hamiltonian(2, m2, numpy=True)
    term3 = Hamiltonian(1, m3, numpy=True)
    parts = [{(0, 1, 2): term1}, {(2, 3): term2, (1, ): term3}]
    trotter_h = TrotterHamiltonian(*parts)

    # Test that the `TrotterHamiltonian` dense matrix is correct
    eye = np.eye(2, dtype=m1.dtype)
    mm1 = np.kron(m1, eye)
    mm2 = np.kron(np.kron(eye, eye), m2)
    mm3 = np.kron(np.kron(eye, m3), np.kron(eye, eye))
    target_h = Hamiltonian(4, mm1 + mm2 + mm3)
    np.testing.assert_allclose(trotter_h.dense.matrix, target_h.matrix)

    dt = 1e-2
    initial_state = utils.random_numpy_state(4)
    if backend == "custom":
        with pytest.raises(NotImplementedError):
            circuit = trotter_h.circuit(dt=dt)
    else:
        circuit = trotter_h.circuit(dt=dt)
        final_state = circuit(np.copy(initial_state))

        u = [expm(-0.5j * dt * m) for m in [mm1, mm2, mm3]]
        target_state = u[2].dot(u[1].dot(u[0])).dot(initial_state)
        target_state = u[0].dot(u[1].dot(u[2])).dot(target_state)
        np.testing.assert_allclose(final_state, target_state)

    qibo.set_backend(original_backend)
예제 #9
0
def test_trotter_hamiltonian_operation_errors():
    """Test errors in ``TrotterHamiltonian`` addition and subtraction."""
    # test addition with different number of parts
    h1 = TFIM(nqubits=5, trotter=True)
    term = TFIM(nqubits=2, numpy=True)
    h2 = TrotterHamiltonian({
        (0, 1): term,
        (2, 3): term,
        (4, 0): term
    }, {
        (1, 2): term,
        (3, 4): term
    })
    with pytest.raises(ValueError):
        h = h1 + h2
    # test subtraction with incompatible parts
    h2 = TrotterHamiltonian({
        (0, 1): term,
        (2, 3): term
    }, {(1, 2): term}, {(4, 0): term})
    with pytest.raises(ValueError):
        h = h1 - h2
    # test matmul with bad type
    with pytest.raises(NotImplementedError):
        s = h1 @ "abc"
    # test matmul with bad shape
    with pytest.raises(ValueError):
        s = h1 @ np.zeros((2, 2))
    # test ``make_compatible`` with non-Trotter Hamiltonian
    with pytest.raises(TypeError):
        h2 = h1.make_compatible("test")
    # test ``make_compatible`` with interacting Hamiltonian
    with pytest.raises(NotImplementedError):
        h2 = h1.make_compatible(h2)
    # test ``make_compatible`` with insufficient two-qubit terms
    h3 = X(nqubits=7, trotter=True)
    with pytest.raises(ValueError):
        h3 = h1.make_compatible(h3)
예제 #10
0
def test_x_hamiltonian_from_symbols(nqubits, trotter):
    """Check creating sum(X) Hamiltonian using sympy."""
    import sympy
    x_symbols = sympy.symbols(" ".join((f"X{i}" for i in range(nqubits))))
    symham = -sum(x_symbols)
    symmap = {x: (i, matrices.X) for i, x in enumerate(x_symbols)}

    target_matrix = X(nqubits).matrix
    if trotter:
        trotter_ham = TrotterHamiltonian.from_symbolic(symham, symmap)
        final_matrix = trotter_ham.dense.matrix
    else:
        full_ham = Hamiltonian.from_symbolic(symham, symmap)
        final_matrix = full_ham.matrix
    np.testing.assert_allclose(final_matrix, target_matrix)
예제 #11
0
def test_trotter_hamiltonian_make_compatible_onequbit_terms():
    """Check ``make_compatible`` when the two-qubit Hamiltonian has one-qubit terms."""
    term1 = Hamiltonian(1, matrices.Z, numpy=True)
    term2 = Hamiltonian(2, np.kron(matrices.Z, matrices.Z), numpy=True)
    terms = {
        (0, 1): term2,
        (0, 2): -0.5 * term2,
        (1, 2): 2 * term2,
        (1, ): 0.35 * term1,
        (2, 3): 0.25 * term2,
        (2, ): 0.5 * term1,
        (3, ): term1
    }
    tham = TrotterHamiltonian.from_dictionary(terms) + 1.5
    xham = X(nqubits=4, trotter=True)
    cxham = tham.make_compatible(xham)
    assert not tham.is_compatible(xham)
    assert tham.is_compatible(cxham)
    np.testing.assert_allclose(xham.dense.matrix, cxham.dense.matrix)
예제 #12
0
def test_tfim_hamiltonian_from_symbols(nqubits, trotter):
    """Check creating TFIM Hamiltonian using sympy."""
    import sympy
    h = 0.5
    z_symbols = sympy.symbols(" ".join((f"Z{i}" for i in range(nqubits))))
    x_symbols = sympy.symbols(" ".join((f"X{i}" for i in range(nqubits))))

    symham = sum(z_symbols[i] * z_symbols[i + 1] for i in range(nqubits - 1))
    symham += z_symbols[0] * z_symbols[-1]
    symham += h * sum(x_symbols)
    symmap = {z: (i, matrices.Z) for i, z in enumerate(z_symbols)}
    symmap.update({x: (i, matrices.X) for i, x in enumerate(x_symbols)})

    target_matrix = TFIM(nqubits, h=h).matrix
    if trotter:
        trotter_ham = TrotterHamiltonian.from_symbolic(-symham, symmap)
        final_matrix = trotter_ham.dense.matrix
    else:
        full_ham = Hamiltonian.from_symbolic(-symham, symmap)
        final_matrix = full_ham.matrix
    np.testing.assert_allclose(final_matrix, target_matrix)
예제 #13
0
def test_three_qubit_term_hamiltonian_from_symbols(trotter):
    """Check creating Hamiltonian with three-qubit interaction using sympy."""
    import sympy
    from qibo import matrices
    x_symbols = sympy.symbols(" ".join((f"X{i}" for i in range(4))))
    y_symbols = sympy.symbols(" ".join((f"Y{i}" for i in range(4))))
    z_symbols = sympy.symbols(" ".join((f"Z{i}" for i in range(4))))
    symmap = {x: (i, matrices.X) for i, x in enumerate(x_symbols)}
    symmap.update({x: (i, matrices.Y) for i, x in enumerate(y_symbols)})
    symmap.update({x: (i, matrices.Z) for i, x in enumerate(z_symbols)})

    symham = x_symbols[0] * y_symbols[1] * z_symbols[2]
    symham += 0.5 * y_symbols[0] * z_symbols[1] * x_symbols[3]
    symham += z_symbols[0] * x_symbols[2]
    symham += -3 * x_symbols[1] * y_symbols[3]
    symham += y_symbols[2]
    symham += 1.5 * z_symbols[1]
    symham -= 2

    target_matrix = np.kron(np.kron(matrices.X, matrices.Y),
                            np.kron(matrices.Z, matrices.I))
    target_matrix += 0.5 * np.kron(np.kron(matrices.Y, matrices.Z),
                                   np.kron(matrices.I, matrices.X))
    target_matrix += np.kron(np.kron(matrices.Z, matrices.I),
                             np.kron(matrices.X, matrices.I))
    target_matrix += -3 * np.kron(np.kron(matrices.I, matrices.X),
                                  np.kron(matrices.I, matrices.Y))
    target_matrix += np.kron(np.kron(matrices.I, matrices.I),
                             np.kron(matrices.Y, matrices.I))
    target_matrix += 1.5 * np.kron(np.kron(matrices.I, matrices.Z),
                                   np.kron(matrices.I, matrices.I))
    target_matrix -= 2 * np.eye(2**4, dtype=target_matrix.dtype)
    if trotter:
        trotter_ham = TrotterHamiltonian.from_symbolic(symham, symmap)
        final_matrix = trotter_ham.dense.matrix
    else:
        full_ham = Hamiltonian.from_symbolic(symham, symmap)
        final_matrix = full_ham.matrix
    np.testing.assert_allclose(final_matrix, target_matrix)
예제 #14
0
def test_from_symbolic_with_power(trotter):
    """Check ``from_symbolic`` when the expression contains powers."""
    import sympy
    z = sympy.symbols(" ".join((f"Z{i}" for i in range(3))))
    symham = z[0]**2 - z[1]**2 + 3 * z[1] - 2 * z[0] * z[2] + +1
    matrix = utils.random_numpy_hermitian(1)
    symmap = {x: (i, matrix) for i, x in enumerate(z)}
    if trotter:
        ham = TrotterHamiltonian.from_symbolic(symham, symmap)
        final_matrix = ham.dense.matrix
    else:
        ham = Hamiltonian.from_symbolic(symham, symmap)
        final_matrix = ham.matrix

    matrix2 = matrix.dot(matrix)
    eye = np.eye(2, dtype=matrix.dtype)
    target_matrix = np.kron(np.kron(matrix2, eye), eye)
    target_matrix -= np.kron(np.kron(eye, matrix2), eye)
    target_matrix += 3 * np.kron(np.kron(eye, matrix), eye)
    target_matrix -= 2 * np.kron(np.kron(matrix, eye), matrix)
    target_matrix += np.eye(8, dtype=matrix.dtype)
    np.testing.assert_allclose(final_matrix, target_matrix)