Ejemplo n.º 1
0
def test_hamiltonian_matmul(backend, sparse_type):
    """Test matrix multiplication between Hamiltonians."""
    if sparse_type is None:
        nqubits = 3
        H1 = hamiltonians.TFIM(nqubits, h=1.0)
        H2 = hamiltonians.Y(nqubits)
    else:
        nqubits = 5
        nstates = 2 ** nqubits
        H1 = hamiltonians.Hamiltonian(nqubits, random_sparse_matrix(nstates, sparse_type))
        H2 = hamiltonians.Hamiltonian(nqubits, random_sparse_matrix(nstates, sparse_type))

    m1 = K.to_numpy(H1.matrix)
    m2 = K.to_numpy(H2.matrix)
    if K.name == "tensorflow" and sparse_type is not None:
        with pytest.raises(NotImplementedError):
            _ = H1 @ H2
    else:
        K.assert_allclose((H1 @ H2).matrix, m1 @ m2)
        K.assert_allclose((H2 @ H1).matrix, m2 @ m1)

    with pytest.raises(ValueError):
        H1 @ np.zeros(3 * (2 ** nqubits,), dtype=m1.dtype)
    with pytest.raises(NotImplementedError):
        H1 @ 2
Ejemplo n.º 2
0
def test_hamiltonian_algebraic_operations(dtype, sparse_type):
    """Test basic hamiltonian overloading."""

    def transformation_a(a, b):
        c1 = dtype(0.1)
        return a + c1 * b
    def transformation_b(a, b):
        c1 = dtype(2)
        c2 = dtype(3.5)
        return c1 * a - b * c2
    def transformation_c(a, b, use_eye=False):
        c1 = dtype(4.5)
        if use_eye:
            return a + c1 * np.eye(a.shape[0]) - b
        else:
            return a + c1 - b
    def transformation_d(a, b, use_eye=False):
        c1 = dtype(10.5)
        c2 = dtype(2)
        if use_eye:
            return c1 * np.eye(a.shape[0]) - a + c2 * b
        else:
            return c1 - a + c2 * b

    if sparse_type is None:
        H1 = hamiltonians.XXZ(nqubits=2, delta=0.5)
        H2 = hamiltonians.XXZ(nqubits=2, delta=1)
        mH1, mH2 = K.to_numpy(H1.matrix), K.to_numpy(H2.matrix)
    else:
        mH1 = sparse.rand(64, 64, format=sparse_type)
        mH2 = sparse.rand(64, 64, format=sparse_type)
        H1 = hamiltonians.Hamiltonian(6, mH1)
        H2 = hamiltonians.Hamiltonian(6, mH2)

    hH1 = transformation_a(mH1, mH2)
    hH2 = transformation_b(mH1, mH2)
    hH3 = transformation_c(mH1, mH2, use_eye=True)
    hH4 = transformation_d(mH1, mH2, use_eye=True)

    HT1 = transformation_a(H1, H2)
    HT2 = transformation_b(H1, H2)
    HT3 = transformation_c(H1, H2)
    HT4 = transformation_d(H1, H2)

    K.assert_allclose(hH1, HT1.matrix)
    K.assert_allclose(hH2, HT2.matrix)
    K.assert_allclose(hH3, HT3.matrix)
    K.assert_allclose(hH4, HT4.matrix)
Ejemplo n.º 3
0
def test_trotter_hamiltonian_three_qubit_term(backend):
    """Test creating ``TrotterHamiltonian`` with three qubit term."""
    from scipy.linalg import expm
    from qibo.core.terms import HamiltonianTerm
    m1 = random_hermitian(3)
    m2 = random_hermitian(2)
    m3 = random_hermitian(1)

    terms = [HamiltonianTerm(m1, 0, 1, 2), HamiltonianTerm(m2, 2, 3),
             HamiltonianTerm(m3, 1)]
    ham = hamiltonians.SymbolicHamiltonian()
    ham.terms = terms

    # 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_ham = hamiltonians.Hamiltonian(4, mm1 + mm2 + mm3)
    K.assert_allclose(ham.matrix, target_ham.matrix)

    dt = 1e-2
    initial_state = random_state(4)
    if K.op is not None:
        with pytest.raises(NotImplementedError):
            circuit = ham.circuit(dt=dt)
    else:
        circuit = ham.circuit(dt=dt)
        final_state = circuit(np.copy(initial_state))
        u = [expm(-0.5j * dt * (mm1 + mm3)), expm(-0.5j * dt * mm2)]
        target_state = u[1].dot(u[0].dot(initial_state))
        target_state = u[0].dot(u[1].dot(target_state))
        K.assert_allclose(final_state, target_state)
Ejemplo n.º 4
0
 def construct_hamiltonian():
     if sparse_type is None:
         return hamiltonians.XXZ(nqubits=2, delta=0.5, dense=dense)
     else:
         ham = hamiltonians.XXZ(nqubits=5, delta=0.5)
         m = getattr(sparse, f"{sparse_type}_matrix")(K.to_numpy(ham.matrix))
         return hamiltonians.Hamiltonian(5, m)
Ejemplo n.º 5
0
def test_hamiltonian_eigenvalues(dtype, sparse_type, dense):
    """Testing hamiltonian eigenvalues scaling."""
    if sparse_type is None:
        H1 = hamiltonians.XXZ(nqubits=2, delta=0.5, dense=dense)
    else:
        from scipy import sparse
        H1 = hamiltonians.XXZ(nqubits=5, delta=0.5)
        m = getattr(sparse, f"{sparse_type}_matrix")(K.to_numpy(H1.matrix))
        H1 = hamiltonians.Hamiltonian(5, m)

    H1_eigen = sorted(K.to_numpy(H1.eigenvalues()))
    hH1_eigen = sorted(K.to_numpy(K.eigvalsh(H1.matrix)))
    K.assert_allclose(sorted(H1_eigen), hH1_eigen)

    c1 = dtype(2.5)
    H2 = c1 * H1
    H2_eigen = sorted(K.to_numpy(H2._eigenvalues))
    hH2_eigen = sorted(K.to_numpy(K.eigvalsh(c1 * H1.matrix)))
    K.assert_allclose(H2_eigen, hH2_eigen)

    c2 = dtype(-11.1)
    H3 = H1 * c2
    if sparse_type is None:
        H3_eigen = sorted(K.to_numpy(H3._eigenvalues))
        hH3_eigen = sorted(K.to_numpy(K.eigvalsh(H1.matrix * c2)))
        K.assert_allclose(H3_eigen, hH3_eigen)
    else:
        assert H3._eigenvalues is None
Ejemplo n.º 6
0
def h0t():
    """Generate the 2 qubit Hamiltonian for Trotter evolution, equivalent to the intial Hamiltonian.
    Returns:
        h0t (Hamiltonian): 4 x 4 Hamiltonian used as a base for the initial Hamiltonian.
    """
    m0 = 0.5 * np.kron(matrices.I - matrices.X, matrices.I)
    return hamiltonians.Hamiltonian(2, m0, numpy=True)
Ejemplo n.º 7
0
def h_ct():
    """Generate the 2 qubit Hamiltonian for Trotter evolution, equivalent to the clause Hamiltonian.
    Returns:
        h_ct (Hamiltonian): 4 x 4 Hamiltonian used as a base for the problem Hamiltonian.
    """
    m1 = 0.5 * (np.kron(matrices.Z, matrices.Z) -
                np.kron(matrices.Z, matrices.I))
    return hamiltonians.Hamiltonian(2, m1, numpy=True)
Ejemplo n.º 8
0
def test_hamiltonian_ground_state(sparse_type, dense):
    """Test Hamiltonian ground state."""
    if sparse_type is None:
        H = hamiltonians.XXZ(nqubits=2, delta=0.5, dense=dense)
    else:
        from scipy import sparse
        H = hamiltonians.XXZ(nqubits=5, delta=0.5)
        m = getattr(sparse, f"{sparse_type}_matrix")(K.to_numpy(H.matrix))
        H = hamiltonians.Hamiltonian(5, m)
    V = K.to_numpy(H.eigenvectors())
    K.assert_allclose(H.ground_state(), V[:, 0])
Ejemplo n.º 9
0
def test_hamiltonian_init():
    with pytest.raises(TypeError):
        H = hamiltonians.Hamiltonian(2, "test")
    H1 = hamiltonians.Hamiltonian(2, np.eye(4))
    H1 = hamiltonians.Hamiltonian(2, np.eye(4))
    H1 = hamiltonians.Hamiltonian(2, K.eye(4))
    H1 = hamiltonians.Hamiltonian(2, K.eye(4))
    with pytest.raises(ValueError):
        H1 = hamiltonians.Hamiltonian(-2, np.eye(4))
    with pytest.raises(RuntimeError):
        H2 = hamiltonians.Hamiltonian(np.eye(2), np.eye(4))
    with pytest.raises(ValueError):
        H3 = hamiltonians.Hamiltonian(4, np.eye(10))
Ejemplo n.º 10
0
    def dense(self):
        """Creates an equivalent Hamiltonian model that holds the full matrix.

        Returns:
            A :class:`qibo.base.hamiltonians.Hamiltonian` object that is
            equivalent to this local Hamiltonian.
        """
        if self._dense is None:
            from qibo import hamiltonians
            matrix = self._calculate_dense_matrix() # pylint: disable=E1111
            self.dense = hamiltonians.Hamiltonian(self.nqubits, matrix)
        return self._dense
Ejemplo n.º 11
0
def test_hamiltonian_addition(sparse_type):
    if sparse_type is None:
        H1 = hamiltonians.Y(nqubits=3)
        H2 = hamiltonians.TFIM(nqubits=3, h=1.0)
    else:
        H1 = hamiltonians.Hamiltonian(6, sparse.rand(64, 64, format=sparse_type))
        H2 = hamiltonians.Hamiltonian(6, sparse.rand(64, 64, format=sparse_type))

    H = H1 + H2
    matrix = H1.matrix + H2.matrix
    K.assert_allclose(H.matrix, matrix)
    H = H1 - 0.5 * H2
    matrix = H1.matrix - 0.5 * H2.matrix
    K.assert_allclose(H.matrix, matrix)

    H1 = hamiltonians.XXZ(nqubits=2, delta=0.5)
    H2 = hamiltonians.XXZ(nqubits=3, delta=0.1)
    with pytest.raises(RuntimeError):
        R = H1 + H2
    with pytest.raises(RuntimeError):
        R = H1 - H2
Ejemplo n.º 12
0
    def encoder_hamiltonian_simple(nqubits, ncompress):
        """Creates the encoding Hamiltonian.
        Args:
            nqubits (int): total number of qubits.
            ncompress (int): number of discarded/trash qubits.

        Returns:
            Encoding Hamiltonian.
        """
        m0 = K.to_numpy(hamiltonians.Z(ncompress).matrix)
        m1 = np.eye(2**(nqubits - ncompress), dtype=m0.dtype)
        ham = hamiltonians.Hamiltonian(nqubits, np.kron(m1, m0))
        return 0.5 * (ham + ncompress)
Ejemplo n.º 13
0
 def hamiltonian(nqubits, position):
     identity = [[1, 0], [0, 1]]
     m0 = hamiltonians.Z(1).matrix
     kron = []
     for i in range(nqubits):
         if i == position:
             kron.append(m0)
         else:
             kron.append(identity)
     for i in range(nqubits - 1):
         if i == 0:
             ham = np.kron(kron[i + 1], kron[i])
         else:
             ham = np.kron(kron[i + 1], ham)
     ham = hamiltonians.Hamiltonian(nqubits, ham)
     return ham
Ejemplo n.º 14
0
def test_hamiltonian_expectation(backend, dense, density_matrix, sparse_type):
    """Test Hamiltonian expectation value calculation."""
    if sparse_type is None:
        h = hamiltonians.XXZ(nqubits=3, delta=0.5, dense=dense)
    else:
        h = hamiltonians.Hamiltonian(6, random_sparse_matrix(64, sparse_type))

    matrix = K.to_numpy(h.matrix)
    if density_matrix:
        state = random_complex((2 ** h.nqubits, 2 ** h.nqubits))
        state = state + state.T.conj()
        norm = np.trace(state)
        target_ev = np.trace(matrix.dot(state)).real
    else:
        state = random_complex(2 ** h.nqubits)
        norm = np.sum(np.abs(state) ** 2)
        target_ev = np.sum(state.conj() * matrix.dot(state)).real

    K.assert_allclose(h.expectation(state), target_ev)
    K.assert_allclose(h.expectation(state, True), target_ev / norm)
Ejemplo n.º 15
0
def test_hamiltonian_matmul_states(backend, sparse_type):
    """Test matrix multiplication between Hamiltonian and states."""
    if sparse_type is None:
        nqubits = 3
        H = hamiltonians.TFIM(nqubits, h=1.0)
    else:
        nqubits = 5
        nstates = 2 ** nqubits
        H = hamiltonians.Hamiltonian(nqubits, random_sparse_matrix(nstates, sparse_type))

    hm = K.to_numpy(H.matrix)
    v = random_complex(2 ** nqubits, dtype=hm.dtype)
    m = random_complex((2 ** nqubits, 2 ** nqubits), dtype=hm.dtype)
    Hv = H @ K.cast(v)
    Hm = H @ K.cast(m)
    K.assert_allclose(Hv, hm.dot(v))
    K.assert_allclose(Hm, hm @ m)

    from qibo.core.states import VectorState
    Hstate = H @ VectorState.from_tensor(K.cast(v))
    K.assert_allclose(Hstate, hm.dot(v))
Ejemplo n.º 16
0
def main(nqubits, instance, T, dt, solver, plot, trotter, params, method,
         maxiter):
    """Adiabatic evoluition to find the solution of an exact cover instance.

    Args:
        nqubits (int): number of qubits for the file that contains the
            information of an Exact Cover instance.
        instance (int): intance used for the desired number of qubits.
        T (float): maximum schedule time. The larger T, better final results.
        dt (float): time interval for the evolution.
        solver (str): solver used for the adiabatic evolution.
        plot (bool): decides if plots of the energy and gap will be returned.
        trotter (bool): decides if a Trotter Hamiltonian will be used.
        params (list): list of polynomial coefficients for scheduling function.
            Default is linear scheduling.
        method (str): Method to use for scheduling optimization (optional).
        maxiter (bool): Maximum iterations for scheduling optimization (optional).

    Returns:
        Result of the most probable outcome after the adiabatic evolution.
        Plots of the ground and excited state energies and the underlying gap
        during the adiabatic evolution. The plots are created only if the
        ``--plot`` option is enabled.
    """
    # Read 3SAT clauses from file
    control, solution, clauses = functions.read_file(nqubits, instance)
    nqubits = int(control[0])
    # Define "easy" and "problem" Hamiltonians
    if trotter:
        print('Using Trotter decomposition for the Hamiltonian\n')
        parts0, parts1 = functions.trotter_dict(clauses)
        gs = lambda: functions.ground_state(nqubits)
        H0 = hamiltonians.TrotterHamiltonian(*parts0, ground_state=gs)
        H1 = hamiltonians.TrotterHamiltonian(*parts1) + len(clauses)
    else:
        print('Using the full Hamiltonian evolution\n')
        t = functions.times(nqubits, clauses)
        H0 = hamiltonians.Hamiltonian(nqubits, functions.h0(nqubits, t))
        H1 = hamiltonians.Hamiltonian(nqubits, functions.h_p(nqubits, clauses))

    print('-' * 20 + '\n')
    if plot and nqubits >= 14:
        print('Currently not possible to calculate gap energy for {} qubits.'
              '\n Proceeding to adiabatic evolution without plotting data.\n'
              ''.format(nqubits))
        plot = False
    if plot and method is not None:
        print('Not possible to calculate gap energy during optimization.')
        plot = False

    # Define scheduling according to given params
    if params is None:
        # default is linear scheduling
        s = lambda t: t
    else:
        if method is None:
            s = lambda t: functions.spolynomial(t, params)
        else:
            s = functions.spolynomial

    # Define evolution model and (optionally) callbacks
    if plot:
        ground = callbacks.Gap(0)
        excited = callbacks.Gap(1)
        gap = callbacks.Gap()
        evolve = models.AdiabaticEvolution(H0,
                                           H1,
                                           s,
                                           dt,
                                           solver=solver,
                                           callbacks=[gap, ground, excited])
    else:
        evolve = models.AdiabaticEvolution(H0, H1, s, dt, solver=solver)

    if method is not None:
        print(f'Optimizing scheduling using {method}.\n')
        if params is None:
            params = [T]
        else:
            params.append(T)
        if method == "sgd":
            options = {"nepochs": maxiter}
        else:
            options = {"maxiter": maxiter, "disp": True}
        energy, params = evolve.minimize(params,
                                         method=method,
                                         options=options)
        T = params[-1]

    # Perform evolution
    initial_state = np.ones(2**nqubits) / np.sqrt(2**nqubits)
    final_state = evolve(final_time=T, initial_state=initial_state)
    output_dec = (np.abs(final_state.numpy())**2).argmax()
    max_output = "{0:0{bits}b}".format(output_dec, bits=nqubits)
    max_prob = (np.abs(final_state.numpy())**2).max()
    print("Exact cover instance with {} qubits.\n".format(nqubits))
    if solution:
        print('Known solution: {}\n'.format(''.join(solution)))
    print('-' * 20 + '\n')
    print(f'Adiabatic evolution with total time {T}, evolution step {dt} and '
          f'solver {solver}.\n')
    print(f'Most common solution after adiabatic evolution: {max_output}.\n')
    print(f'Found with probability: {max_prob}.\n')
    if plot:
        print('-' * 20 + '\n')
        functions.plot(nqubits, ground[:], excited[:], gap[:], dt, T)
        print('Plots finished.\n')