def setUp(self):
        self.x_dimension = 2
        self.y_dimension = 3

        # Create a Hamiltonian with nearest-neighbor hopping terms
        self.ferm_op = fermi_hubbard(self.x_dimension, self.y_dimension, 1., 0.,
                                     0., 0., False, True)

        # Get the ground energy and ground state
        self.ferm_op_sparse = get_sparse_operator(self.ferm_op)
        self.ferm_op_ground_energy, self.ferm_op_ground_state = (
            get_ground_state(self.ferm_op_sparse))

        # Transform the FermionOperator to a QubitOperator
        self.transformed_op = verstraete_cirac_2d_square(
            self.ferm_op,
            self.x_dimension,
            self.y_dimension,
            add_auxiliary_hamiltonian=True,
            snake=False)

        # Get the ground energy and state of the transformed operator
        self.transformed_sparse = get_sparse_operator(self.transformed_op)
        self.transformed_ground_energy, self.transformed_ground_state = (
            get_ground_state(self.transformed_sparse))
예제 #2
0
    def test_from_integrals_to_qubit(self):
        hamiltonian = jordan_wigner(self.molecule.get_molecular_hamiltonian())
        doci_hamiltonian = DOCIHamiltonian.from_integrals(
            constant=self.molecule.nuclear_repulsion,
            one_body_integrals=self.molecule.one_body_integrals,
            two_body_integrals=self.molecule.two_body_integrals).qubit_operator

        hamiltonian_matrix = get_sparse_operator(hamiltonian).toarray()
        doci_hamiltonian_matrix = get_sparse_operator(
            doci_hamiltonian).toarray()
        diagonal = numpy.real(numpy.diag(hamiltonian_matrix))
        doci_diagonal = numpy.real(numpy.diag(doci_hamiltonian_matrix))
        position_of_doci_diag_in_h = [0] * len(doci_diagonal)
        for idx, doci_eigval in enumerate(doci_diagonal):
            closest_in_diagonal = None
            for idx2, eig in enumerate(diagonal):
                if closest_in_diagonal is None or abs(eig - doci_eigval) < abs(
                        closest_in_diagonal - doci_eigval):
                    closest_in_diagonal = eig
                    position_of_doci_diag_in_h[idx] = idx2
            assert abs(closest_in_diagonal - doci_eigval) < EQ_TOLERANCE, (
                "Value " + str(doci_eigval) + " of the DOCI Hamiltonian " +
                "diagonal did not appear in the diagonal of the full " +
                "Hamiltonian. The closest value was " +
                str(closest_in_diagonal))

        sub_matrix = hamiltonian_matrix[numpy.ix_(position_of_doci_diag_in_h,
                                                  position_of_doci_diag_in_h)]
        assert numpy.allclose(doci_hamiltonian_matrix, sub_matrix), (
            "The coupling between the DOCI states in the DOCI Hamiltonian " +
            "should be identical to that between these states in the full " +
            "Hamiltonian but the DOCI hamiltonian matrix\n" +
            str(doci_hamiltonian_matrix) +
            "\ndoes not match the corresponding sub-matrix of the full " +
            "Hamiltonian\n" + str(sub_matrix))
예제 #3
0
    def test_model_integration_with_constant(self):
        # Compute Hamiltonian in both momentum and position space.
        length_scale = 0.7
        for length in [2, 3]:
            grid = Grid(dimensions=2, length=length, scale=length_scale)
            spinless = True

            # Include Madelung constant in the momentum but not the position
            # Hamiltonian.
            momentum_hamiltonian = jellium_model(grid,
                                                 spinless,
                                                 True,
                                                 include_constant=True)
            position_hamiltonian = jellium_model(grid, spinless, False)

            # Confirm they are Hermitian
            momentum_hamiltonian_operator = (
                get_sparse_operator(momentum_hamiltonian))
            self.assertTrue(is_hermitian(momentum_hamiltonian_operator))

            position_hamiltonian_operator = (
                get_sparse_operator(position_hamiltonian))
            self.assertTrue(is_hermitian(position_hamiltonian_operator))

            # Diagonalize and confirm the same energy.
            jw_momentum = jordan_wigner(momentum_hamiltonian)
            jw_position = jordan_wigner(position_hamiltonian)
            momentum_spectrum = eigenspectrum(jw_momentum)
            position_spectrum = eigenspectrum(jw_position)

            # Confirm momentum spectrum is shifted 2.8372/length_scale higher.
            max_difference = numpy.amax(momentum_spectrum - position_spectrum)
            min_difference = numpy.amax(momentum_spectrum - position_spectrum)
            self.assertAlmostEqual(max_difference, 2.8372 / length_scale)
            self.assertAlmostEqual(min_difference, 2.8372 / length_scale)
예제 #4
0
    def test_plane_wave_hamiltonian_integration(self):
        length_set = [2, 3, 4]
        spinless_set = [True, False]
        length_scale = 1.1
        for geometry in [[('H', (0,)), ('H', (0.8,))], [('H', (0.1,))],
                         [('H', (0.1,))]]:
            for l in length_set:
                for spinless in spinless_set:
                    grid = Grid(dimensions=1, scale=length_scale, length=l)
                    h_plane_wave = plane_wave_hamiltonian(
                        grid, geometry, spinless, True, include_constant=False)
                    h_dual_basis = plane_wave_hamiltonian(
                        grid, geometry, spinless, False, include_constant=False)

                    # Test for Hermiticity
                    plane_wave_operator = get_sparse_operator(h_plane_wave)
                    dual_operator = get_sparse_operator(h_dual_basis)
                    self.assertTrue(is_hermitian((plane_wave_operator)))
                    self.assertTrue(is_hermitian(dual_operator))

                    jw_h_plane_wave = jordan_wigner(h_plane_wave)
                    jw_h_dual_basis = jordan_wigner(h_dual_basis)
                    h_plane_wave_spectrum = eigenspectrum(jw_h_plane_wave)
                    h_dual_basis_spectrum = eigenspectrum(jw_h_dual_basis)

                    max_diff = np.amax(h_plane_wave_spectrum -
                                       h_dual_basis_spectrum)
                    min_diff = np.amin(h_plane_wave_spectrum -
                                       h_dual_basis_spectrum)
                    self.assertAlmostEqual(max_diff, 0)
                    self.assertAlmostEqual(min_diff, 0)
예제 #5
0
    def test_potential_integration(self):
        # Compute potential energy operator in momentum and position space.
        for length in [2, 3]:
            grid = Grid(dimensions=2, length=length, scale=2.)
            spinless = True
            momentum_potential = plane_wave_potential(grid, spinless)
            position_potential = dual_basis_potential(grid, spinless)

            # Confirm they are Hermitian
            momentum_potential_operator = (
                get_sparse_operator(momentum_potential))
            self.assertTrue(is_hermitian(momentum_potential_operator))

            position_potential_operator = (
                get_sparse_operator(position_potential))
            self.assertTrue(is_hermitian(position_potential_operator))

            # Diagonalize and confirm the same energy.
            jw_momentum = jordan_wigner(momentum_potential)
            jw_position = jordan_wigner(position_potential)
            momentum_spectrum = eigenspectrum(jw_momentum)
            position_spectrum = eigenspectrum(jw_position)

            # Confirm spectra are the same.
            difference = numpy.amax(
                numpy.absolute(momentum_spectrum - position_spectrum))
            self.assertAlmostEqual(difference, 0.)
예제 #6
0
    def test_model_integration(self):
        # Compute Hamiltonian in both momentum and position space.
        for length in [2, 3]:
            grid = Grid(dimensions=2, length=length, scale=1.0)
            spinless = True
            momentum_hamiltonian = jellium_model(grid, spinless, True)
            position_hamiltonian = jellium_model(grid, spinless, False)

            # Confirm they are Hermitian
            momentum_hamiltonian_operator = (
                get_sparse_operator(momentum_hamiltonian))
            self.assertTrue(is_hermitian(momentum_hamiltonian_operator))

            position_hamiltonian_operator = (
                get_sparse_operator(position_hamiltonian))
            self.assertTrue(is_hermitian(position_hamiltonian_operator))

            # Diagonalize and confirm the same energy.
            jw_momentum = jordan_wigner(momentum_hamiltonian)
            jw_position = jordan_wigner(position_hamiltonian)
            momentum_spectrum = eigenspectrum(jw_momentum)
            position_spectrum = eigenspectrum(jw_position)

            # Confirm spectra are the same.
            difference = numpy.amax(
                numpy.absolute(momentum_spectrum - position_spectrum))
            self.assertAlmostEqual(difference, 0.)
    def test_hf_state_energy_same_in_plane_wave_and_dual_basis(self):
        grid_length = 4
        dimension = 1
        wigner_seitz_radius = 10.0
        spinless = False

        n_orbitals = grid_length**dimension
        if not spinless:
            n_orbitals *= 2
        n_particles = n_orbitals // 2

        length_scale = wigner_seitz_length_scale(wigner_seitz_radius,
                                                 n_particles, dimension)

        grid = Grid(dimension, grid_length, length_scale)
        hamiltonian = jellium_model(grid, spinless)
        hamiltonian_dual_basis = jellium_model(grid, spinless, plane_wave=False)

        # Get the Hamiltonians as sparse operators.
        hamiltonian_sparse = get_sparse_operator(hamiltonian)
        hamiltonian_dual_sparse = get_sparse_operator(hamiltonian_dual_basis)

        hf_state = hartree_fock_state_jellium(grid,
                                              n_particles,
                                              spinless,
                                              plane_wave=True)
        hf_state_dual = hartree_fock_state_jellium(grid,
                                                   n_particles,
                                                   spinless,
                                                   plane_wave=False)

        E_HF_plane_wave = expectation(hamiltonian_sparse, hf_state)
        E_HF_dual = expectation(hamiltonian_dual_sparse, hf_state_dual)

        self.assertAlmostEqual(E_HF_dual, E_HF_plane_wave)
예제 #8
0
    def test_fermionic_hamiltonian_from_integrals(self):
        constant = self.molecule.nuclear_repulsion
        doci_constant = constant
        hc, hr1, hr2 = get_doci_from_integrals(
            self.molecule.one_body_integrals, self.molecule.two_body_integrals)

        doci = DOCIHamiltonian(doci_constant, hc, hr1, hr2)

        doci_qubit_op = doci.qubit_operator
        doci_mat = get_sparse_operator(doci_qubit_op).toarray()
        #doci_eigvals, doci_eigvecs = numpy.linalg.eigh(doci_mat)
        doci_eigvals, _ = numpy.linalg.eigh(doci_mat)

        tensors = doci.n_body_tensors
        one_body_tensors, two_body_tensors = tensors[(1, 0)], tensors[(1, 1, 0,
                                                                       0)]
        fermion_op1 = get_fermion_operator(
            InteractionOperator(constant, one_body_tensors,
                                0. * two_body_tensors))

        fermion_op2 = get_fermion_operator(
            InteractionOperator(0, 0 * one_body_tensors,
                                0.5 * two_body_tensors))

        import openfermion as of
        fermion_op1_jw = of.transforms.jordan_wigner(fermion_op1)
        fermion_op2_jw = of.transforms.jordan_wigner(fermion_op2)

        fermion_op_jw = fermion_op1_jw + fermion_op2_jw
        #fermion_eigvals, fermion_eigvecs = numpy.linalg.eigh(
        #    get_sparse_operator(fermion_op_jw).toarray())
        fermion_eigvals, _ = numpy.linalg.eigh(
            get_sparse_operator(fermion_op_jw).toarray())

        for eigval in doci_eigvals:
            assert any(abs(fermion_eigvals -
                           eigval) < 1e-6), "The DOCI spectrum should \
            have been contained in the spectrum of the fermionic operators"

        fermion_diagonal = get_sparse_operator(
            fermion_op_jw).toarray().diagonal()
        qubit_diagonal = doci_mat.diagonal()
        assert numpy.isclose(
            fermion_diagonal[0], qubit_diagonal[0]
        ) and numpy.isclose(
            fermion_diagonal[-1], qubit_diagonal[-1]
        ), "The first and last elements of hte qubit and fermionic diagonal of \
        the Hamiltonian maxtrix should be the same as the vaccum should be \
        mapped to the computational all zero state and the completely filled \
        state should be mapped to the all one state"

        print(fermion_diagonal)
        print(qubit_diagonal)
def test_circuit_generation_and_accuracy():
    for dim in range(2, 10):
        qubits = cirq.LineQubit.range(dim)
        u_generator = numpy.random.random(
            (dim, dim)) + 1j * numpy.random.random((dim, dim))
        u_generator = u_generator - numpy.conj(u_generator).T
        assert numpy.allclose(-1 * u_generator, numpy.conj(u_generator).T)

        unitary = scipy.linalg.expm(u_generator)
        circuit = cirq.Circuit()
        circuit.append(optimal_givens_decomposition(qubits, unitary))

        fermion_generator = QubitOperator(()) * 0.0
        for i, j in product(range(dim), repeat=2):
            fermion_generator += jordan_wigner(
                FermionOperator(((i, 1), (j, 0)), u_generator[i, j]))

        true_unitary = scipy.linalg.expm(
            get_sparse_operator(fermion_generator).toarray())
        assert numpy.allclose(true_unitary.conj().T.dot(true_unitary),
                              numpy.eye(2**dim, dtype=complex))

        test_unitary = cirq.unitary(circuit)
        assert numpy.isclose(
            abs(numpy.trace(true_unitary.conj().T.dot(test_unitary))), 2**dim)
예제 #10
0
    def ansatz_element_gradient(ansatz_element,
                                var_parameters,
                                ansatz,
                                q_system,
                                cache=None,
                                init_state_qasm=None,
                                excited_state=0):

        excitations_generators = ansatz_element.excitations_generators
        exc_gen_sparse_matrices = []
        for exc_gen in excitations_generators:
            exc_gen_sparse_matrices.append(
                get_sparse_operator(exc_gen, n_qubits=q_system.n_qubits))
        exc_gen_sparse_matrix = sum(exc_gen_sparse_matrices)

        H_sparse_matrix = QiskitSimBackend.ham_sparse_matrix(
            q_system, excited_state=excited_state)

        commutator_sparse_matrix = H_sparse_matrix * exc_gen_sparse_matrix - exc_gen_sparse_matrix * H_sparse_matrix

        statevector = QiskitSimBackend.statevector_from_ansatz(
            ansatz,
            var_parameters,
            q_system.n_qubits,
            q_system.n_electrons,
            init_state_qasm=init_state_qasm)
        sparse_statevector = scipy.sparse.csr_matrix(statevector)

        grad = sparse_statevector.dot(commutator_sparse_matrix).dot(
            sparse_statevector.conj().transpose()).todense()[0, 0]

        assert grad.imag < config.floating_point_accuracy
        return grad.real
예제 #11
0
    def setUp(self):
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        basis = 'sto-3g'
        multiplicity = 1
        filename = os.path.join(DATA_DIRECTORY, 'H2_sto-3g_singlet_0.7414')
        self.molecule = MolecularData(geometry,
                                      basis,
                                      multiplicity,
                                      filename=filename)
        self.molecule.load()

        # Get molecular Hamiltonian.
        self.molecular_hamiltonian = self.molecule.get_molecular_hamiltonian()

        # Get FCI RDM.
        self.fci_rdm = self.molecule.get_molecular_rdm(use_fci=1)
        # Get explicit coefficients.
        self.nuclear_repulsion = self.molecular_hamiltonian.constant
        self.one_body = self.molecular_hamiltonian.one_body_tensor
        self.two_body = self.molecular_hamiltonian.two_body_tensor

        # Get fermion Hamiltonian.
        self.fermion_hamiltonian = normal_ordered(
            get_fermion_operator(self.molecular_hamiltonian))

        # Get qubit Hamiltonian.
        self.qubit_hamiltonian = jordan_wigner(self.fermion_hamiltonian)

        # Get the sparse matrix.
        self.hamiltonian_matrix = get_sparse_operator(
            self.molecular_hamiltonian)
예제 #12
0
def tfd_exact(N, TFD_model, int_dict):
    '''
    Solves the TFD model exactly
    '''
    J_L_tens = TFD_model[0]
    J_R_tens = TFD_model[1]

    L_indices = range(0, 2*N)
    R_indices = range(2*N, 4*N)
    SYK_L_indices = list(permutations(L_indices,4))
    SYK_R_indices = list(permutations(R_indices,4))
    int_indices = [(l, r) for l, r in zip(L_indices, R_indices)]

    #print(SYK_L_indices)
    #print()
    #print(SYK_R_indices)
    H_L = convert_H_majorana_to_qubit_L(SYK_L_indices, J_L_tens)
    H_R = convert_H_majorana_to_qubit_R(SYK_R_indices, J_R_tens, N)
    H_int = convert_H_majorana_to_qubit_L(int_indices, int_dict)

    total_ham = H_L + H_R + H_int
    matrix_ham = get_sparse_operator(total_ham) # todense() allows for ED

    # Diagonalize qubit hamiltonian to compare the spectrum of variational energy
    e, v = np.linalg.eigh(matrix_ham.todense())    

    return e[:10]
    def test_hf_state_energy_close_to_ground_energy_at_high_density(self):
        grid_length = 8
        dimension = 1
        spinless = True
        n_particles = grid_length**dimension // 2

        # High density -> small length_scale.
        length_scale = 0.25

        grid = Grid(dimension, grid_length, length_scale)
        hamiltonian = jellium_model(grid, spinless)
        hamiltonian_sparse = get_sparse_operator(hamiltonian)

        hf_state = hartree_fock_state_jellium(grid,
                                              n_particles,
                                              spinless,
                                              plane_wave=True)

        restricted_hamiltonian = jw_number_restrict_operator(
            hamiltonian_sparse, n_particles)

        E_g = get_ground_state(restricted_hamiltonian)[0]
        E_HF_plane_wave = expectation(hamiltonian_sparse, hf_state)

        self.assertAlmostEqual(E_g, E_HF_plane_wave, places=5)
    def test_hf_state_plane_wave_basis_lowest_single_determinant_state(self):
        grid_length = 7
        dimension = 1
        spinless = True
        n_particles = 4
        length_scale = 2.0

        grid = Grid(dimension, grid_length, length_scale)
        hamiltonian = jellium_model(grid, spinless)
        hamiltonian_sparse = get_sparse_operator(hamiltonian)

        hf_state = hartree_fock_state_jellium(grid,
                                              n_particles,
                                              spinless,
                                              plane_wave=True)

        HF_energy = expectation(hamiltonian_sparse, hf_state)

        for occupied_orbitals in permutations([1] * n_particles + [0] *
                                              (grid_length - n_particles)):
            state_index = numpy.sum(2**numpy.array(occupied_orbitals))
            HF_competitor = numpy.zeros(2**grid_length)
            HF_competitor[state_index] = 1.0

            self.assertLessEqual(HF_energy,
                                 expectation(hamiltonian_sparse, HF_competitor))
예제 #15
0
def test_richardson_gaudin_hamiltonian(g, n_qubits, expected):
    rg = RichardsonGaudin(g, n_qubits)
    rg_qubit = rg.qubit_operator
    assert rg_qubit == expected

    assert np.array_equal(
        np.sort(np.unique(get_sparse_operator(rg_qubit).diagonal())),
        2 * np.array(list(range((n_qubits + 1) * n_qubits // 2 + 1))))
예제 #16
0
    def setUp(self):
        # Set up molecule.
        geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))]
        basis = 'sto-3g'
        multiplicity = 1
        filename = os.path.join(THIS_DIRECTORY, 'data',
                                'H1-Li1_sto-3g_singlet_1.45')
        self.molecule = MolecularData(geometry,
                                      basis,
                                      multiplicity,
                                      filename=filename)
        self.molecule.load()

        # Get molecular Hamiltonian
        self.molecular_hamiltonian = self.molecule.get_molecular_hamiltonian()
        self.molecular_hamiltonian_no_core = (
            self.molecule.get_molecular_hamiltonian(
                occupied_indices=[0],
                active_indices=range(1, self.molecule.n_orbitals)))

        # Get FCI RDM.
        self.fci_rdm = self.molecule.get_molecular_rdm(use_fci=1)

        # Get explicit coefficients.
        self.nuclear_repulsion = self.molecular_hamiltonian.constant
        self.one_body = self.molecular_hamiltonian.one_body_tensor
        self.two_body = self.molecular_hamiltonian.two_body_tensor

        # Get fermion Hamiltonian.
        self.fermion_hamiltonian = normal_ordered(
            get_fermion_operator(self.molecular_hamiltonian))

        # Get qubit Hamiltonian.
        self.qubit_hamiltonian = jordan_wigner(self.fermion_hamiltonian)

        # Get explicit coefficients.
        self.nuclear_repulsion = self.molecular_hamiltonian.constant
        self.one_body = self.molecular_hamiltonian.one_body_tensor
        self.two_body = self.molecular_hamiltonian.two_body_tensor

        # Get matrix form.
        self.hamiltonian_matrix = get_sparse_operator(
            self.molecular_hamiltonian)
        self.hamiltonian_matrix_no_core = get_sparse_operator(
            self.molecular_hamiltonian_no_core)
def tfd_exact(N, J):
    '''
    Solves the TFD model exactly
    '''
    indices = list(permutations(range(0, 2 * N), 4))
    ham = convert_H_majorana_to_qubit(indices, J)
    matrix_ham = get_sparse_operator(ham)  # todense() allows for ED

    # Diagonalize qubit hamiltonian to compare the spectrum of variational energy
    e, v = np.linalg.eigh(matrix_ham.todense())

    return e[:10]
예제 #18
0
 def test_bravyi_kitaev_fast_generate_fermions(self):
     n_qubits = count_qubits(self.molecular_hamiltonian)
     # test for generating two fermions
     edge_matrix = bksf.bravyi_kitaev_fast_edge_matrix(
         self.molecular_hamiltonian)
     edge_matrix_indices = numpy.array(
         numpy.nonzero(
             numpy.triu(edge_matrix) - numpy.diag(numpy.diag(edge_matrix))))
     fermion_generation_operator = bksf.generate_fermions(
         edge_matrix_indices, 2, 3)
     fermion_generation_sp_matrix = get_sparse_operator(
         fermion_generation_operator)
     fermion_generation_matrix = fermion_generation_sp_matrix.toarray()
     bksf_vacuum_state_operator = bksf.vacuum_operator(edge_matrix_indices)
     bksf_vacuum_state_sp_matrix = get_sparse_operator(
         bksf_vacuum_state_operator)
     bksf_vacuum_state_matrix = bksf_vacuum_state_sp_matrix.toarray()
     vacuum_state = numpy.zeros((2**(n_qubits), 1))
     vacuum_state[0] = 1.
     bksf_vacuum_state = numpy.dot(bksf_vacuum_state_matrix, vacuum_state)
     two_fermion_state = numpy.dot(fermion_generation_matrix,
                                   bksf_vacuum_state)
     # using total number operator to check the number of fermions generated
     tot_number_operator = bksf.number_operator(self.molecular_hamiltonian)
     number_operator_sp_matrix = get_sparse_operator(tot_number_operator)
     number_operator_matrix = number_operator_sp_matrix.toarray()
     tot_fermions = numpy.dot(
         two_fermion_state.conjugate().T,
         numpy.dot(number_operator_matrix, two_fermion_state))
     # checking the occupation number of site 2 and 3
     number_operator_2 = bksf.number_operator(self.molecular_hamiltonian, 2)
     number_operator_3 = bksf.number_operator(self.molecular_hamiltonian, 3)
     number_operator_23 = number_operator_2 + number_operator_3
     number_operator_23_sp_matrix = get_sparse_operator(number_operator_23)
     number_operator_23_matrix = number_operator_23_sp_matrix.toarray()
     tot_23_fermions = numpy.dot(
         two_fermion_state.conjugate().T,
         numpy.dot(number_operator_23_matrix, two_fermion_state))
     self.assertTrue(2.0 - float(tot_fermions.real) < 1e-13)
     self.assertTrue(2.0 - float(tot_23_fermions.real) < 1e-13)
    def test_apply_constraints(self):

        # Get norm of original operator.
        original_norm = 0.
        for term, coefficient in self.fermion_hamiltonian.terms.items():
            if term != ():
                original_norm += abs(coefficient)

        # Get modified operator.
        modified_operator = apply_constraints(self.fermion_hamiltonian,
                                              self.n_fermions)
        modified_operator.compress()

        # Get norm of modified operator.
        modified_norm = 0.
        for term, coefficient in modified_operator.terms.items():
            if term != ():
                modified_norm += abs(coefficient)
        self.assertTrue(modified_norm < original_norm)

        # Map both to sparse matrix under Jordan-Wigner.
        sparse_original = get_sparse_operator(self.fermion_hamiltonian)
        sparse_modified = get_sparse_operator(modified_operator)

        # Check spectra.
        sparse_original = jw_number_restrict_operator(sparse_original,
                                                      self.n_fermions)
        sparse_modified = jw_number_restrict_operator(sparse_modified,
                                                      self.n_fermions)
        original_spectrum = sparse_eigenspectrum(sparse_original)
        modified_spectrum = sparse_eigenspectrum(sparse_modified)
        spectral_deviation = numpy.amax(
            numpy.absolute(original_spectrum - modified_spectrum))
        self.assertAlmostEqual(spectral_deviation, 0.)

        # Check expectation value.
        energy, wavefunction = get_ground_state(sparse_original)
        modified_energy = expectation(sparse_modified, wavefunction)
        self.assertAlmostEqual(modified_energy, energy)
    def test_fourier_transform(self):
        for length in [2, 3]:
            grid = Grid(dimensions=1, scale=1.5, length=length)
            spinless_set = [True, False]
            geometry = [('H', (0.1,)), ('H', (0.5,))]
            for spinless in spinless_set:
                h_plane_wave = plane_wave_hamiltonian(grid, geometry, spinless,
                                                      True)
                h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless,
                                                      False)
                h_plane_wave_t = fourier_transform(h_plane_wave, grid, spinless)

                self.assertEqual(normal_ordered(h_plane_wave_t),
                                 normal_ordered(h_dual_basis))

                # Verify that all 3 are Hermitian
                plane_wave_operator = get_sparse_operator(h_plane_wave)
                dual_operator = get_sparse_operator(h_dual_basis)
                plane_wave_t_operator = get_sparse_operator(h_plane_wave_t)
                self.assertTrue(is_hermitian(plane_wave_operator))
                self.assertTrue(is_hermitian(dual_operator))
                self.assertTrue(is_hermitian(plane_wave_t_operator))
예제 #21
0
    def test_kinetic_integration(self):
        # Compute kinetic energy operator in both momentum and position space.
        grid = Grid(dimensions=2, length=2, scale=3.)
        spinless = False
        momentum_kinetic = plane_wave_kinetic(grid, spinless)
        position_kinetic = dual_basis_kinetic(grid, spinless)

        # Confirm they are Hermitian
        momentum_kinetic_operator = get_sparse_operator(momentum_kinetic)
        self.assertTrue(is_hermitian(momentum_kinetic_operator))

        position_kinetic_operator = get_sparse_operator(position_kinetic)
        self.assertTrue(is_hermitian(position_kinetic_operator))

        # Confirm spectral match and hermiticity
        for length in [2, 3, 4]:
            grid = Grid(dimensions=1, length=length, scale=2.1)
            spinless = False

            momentum_kinetic = plane_wave_kinetic(grid, spinless)
            position_kinetic = dual_basis_kinetic(grid, spinless)

            # Confirm they are Hermitian
            momentum_kinetic_operator = get_sparse_operator(momentum_kinetic)
            self.assertTrue(is_hermitian(momentum_kinetic_operator))

            position_kinetic_operator = get_sparse_operator(position_kinetic)
            self.assertTrue(is_hermitian(position_kinetic_operator))

            # Diagonalize and confirm the same energy.
            jw_momentum = jordan_wigner(momentum_kinetic)
            jw_position = jordan_wigner(position_kinetic)
            momentum_spectrum = eigenspectrum(jw_momentum, 2 * length)
            position_spectrum = eigenspectrum(jw_position, 2 * length)

            # Confirm spectra are the same.
            difference = numpy.amax(
                numpy.absolute(momentum_spectrum - position_spectrum))
            self.assertAlmostEqual(difference, 0.)
    def test_constraint_matrix(self):

        # Randomly project operator with constraints.
        numpy.random.seed(8)
        constraints = constraint_matrix(self.n_orbitals, self.n_fermions)
        n_constraints, n_terms = constraints.shape
        self.assertEqual(1 + self.n_orbitals**2 + self.n_orbitals**4, n_terms)
        random_weights = numpy.random.randn(n_constraints)
        vectorized_operator = operator_to_vector(self.fermion_hamiltonian)
        modification_vector = constraints.transpose() * random_weights
        new_operator_vector = vectorized_operator + modification_vector
        modified_operator = vector_to_operator(new_operator_vector,
                                               self.n_orbitals)

        # Map both to sparse matrix under Jordan-Wigner.
        sparse_original = get_sparse_operator(self.fermion_hamiltonian)
        sparse_modified = get_sparse_operator(modified_operator)

        # Check expectation value.
        energy, wavefunction = get_ground_state(sparse_original)
        modified_energy = expectation(sparse_modified, wavefunction)
        self.assertAlmostEqual(modified_energy, energy)
예제 #23
0
def test_fermionic_hamiltonian_from_integrals(g, n_qubits):
    rg = RichardsonGaudin(g, n_qubits)
    #hc, hr1, hr2 = rg.hc, rg.hr1, rg.hr2
    doci = rg
    constant = doci.constant
    reference_constant = 0

    doci_qubit_op = doci.qubit_operator
    doci_mat = get_sparse_operator(doci_qubit_op).toarray()
    doci_eigvals = np.linalg.eigh(doci_mat)[0]

    tensors = doci.n_body_tensors
    one_body_tensors, two_body_tensors = tensors[(1, 0)], tensors[(1, 1, 0, 0)]

    fermion_op = get_fermion_operator(
        InteractionOperator(constant, one_body_tensors, 0.5 * two_body_tensors))
    fermion_op = normal_ordered(fermion_op)
    fermion_mat = get_sparse_operator(fermion_op).toarray()
    fermion_eigvals = np.linalg.eigh(fermion_mat)[0]

    one_body_tensors2, two_body_tensors2 = rg.get_antisymmetrized_tensors()
    fermion_op2 = get_fermion_operator(
        InteractionOperator(reference_constant, one_body_tensors2,
                            0.5 * two_body_tensors2))
    fermion_op2 = normal_ordered(fermion_op2)
    fermion_mat2 = get_sparse_operator(fermion_op2).toarray()
    fermion_eigvals2 = np.linalg.eigh(fermion_mat2)[0]

    for eigval in doci_eigvals:
        assert any(abs(fermion_eigvals -
                       eigval) < 1e-6), "The DOCI spectrum should have \
        been contained in the spectrum of the fermionic operator constructed via the \
        DOCIHamiltonian class"

    for eigval in doci_eigvals:
        assert any(abs(fermion_eigvals2 -
                       eigval) < 1e-6), "The DOCI spectrum should have \
예제 #24
0
def ansatz(q: qreg, x: List[float]):
    X(q[0])
    # The goal of 'with decompose(..) as MAT' is to define a
    # the unitary matrix MAT within the scope of the
    # with statement. Here we use SciPy and Openfermion
    # to construct the X0Y1 - Y0X1 operator as a matrix.
    # Programmers must provide MAT as a numpy.matrix,
    # here todense() maps the sparse operator to a numpy.matrix.
    # Note that if your matrix is dependent on a kernel argument,
    # you must define it in the depends_on=[..] decompose arg.
    with decompose(q, kak) as u:
        from scipy.sparse.linalg import expm
        from openfermion.ops import QubitOperator
        from openfermion.linalg import get_sparse_operator
        qop = QubitOperator('X0 Y1') - QubitOperator('Y0 X1')
        qubit_sparse = get_sparse_operator(qop)
        u = expm(0.5j * x[0] * qubit_sparse).todense()
def test_prepare_gaussian_state_with_spin_symmetry(n_spatial_orbitals,
                                                   conserves_particle_number,
                                                   occupied_orbitals,
                                                   initial_state,
                                                   atol=1e-5):

    n_qubits = 2 * n_spatial_orbitals
    qubits = LineQubit.range(n_qubits)

    # Initialize a random quadratic Hamiltonian
    quad_ham = random_quadratic_hamiltonian(n_spatial_orbitals,
                                            conserves_particle_number,
                                            real=True,
                                            expand_spin=True,
                                            seed=639)

    # Reorder the Hamiltonian and get sparse matrix
    quad_ham = openfermion.get_quadratic_hamiltonian(
        openfermion.reorder(openfermion.get_fermion_operator(quad_ham),
                            openfermion.up_then_down))
    quad_ham_sparse = get_sparse_operator(quad_ham)

    # Compute the energy of the desired state
    energy = 0.0
    for spin_sector in range(2):
        orbital_energies, _, _ = (quad_ham.diagonalizing_bogoliubov_transform(
            spin_sector=spin_sector))
        energy += sum(orbital_energies[i]
                      for i in occupied_orbitals[spin_sector])
    energy += quad_ham.constant

    # Get the state using a circuit simulation
    circuit = cirq.Circuit(
        prepare_gaussian_state(qubits,
                               quad_ham,
                               occupied_orbitals,
                               initial_state=initial_state))

    if isinstance(initial_state, list):
        initial_state = sum(1 << (n_qubits - 1 - i) for i in initial_state)
    state = circuit.final_state_vector(initial_state=initial_state)

    # Check that the result is an eigenstate with the correct eigenvalue
    numpy.testing.assert_allclose(quad_ham_sparse.dot(state),
                                  energy * state,
                                  atol=atol)
예제 #26
0
    def ham_sparse_matrix(q_system, excited_state=0):
        H_sparse_matrix = get_sparse_operator(q_system.jw_qubit_ham)
        if excited_state > 0:
            H_lower_state_terms = q_system.H_lower_state_terms
            assert H_lower_state_terms is not None
            assert len(H_lower_state_terms) >= excited_state
            for i in range(excited_state):
                term = H_lower_state_terms[i]
                state = term[1]
                statevector = QiskitSimBackend.statevector_from_ansatz(
                    state.ansatz_elements,
                    state.parameters,
                    state.n_qubits,
                    state.n_electrons,
                    init_state_qasm=state.init_state_qasm)
                # add the outer product of the lower lying state to the Hamiltonian
                H_sparse_matrix += scipy.sparse.csr_matrix(
                    term[0] * numpy.outer(statevector, statevector))

        return H_sparse_matrix
def test_circuit_generation_state():
    """
    Determine if we rotate the Hartree-Fock state correctly
    """
    simulator = cirq.Simulator()
    circuit = cirq.Circuit()
    qubits = cirq.LineQubit.range(4)
    circuit.append([
        cirq.X(qubits[0]),
        cirq.X(qubits[1]),
        cirq.X(qubits[1]),
        cirq.X(qubits[2]),
        cirq.X(qubits[3]),
        cirq.X(qubits[3])
    ])  # alpha-spins are first then beta spins

    wavefunction = numpy.zeros((2**4, 1), dtype=complex)
    wavefunction[10, 0] = 1.0

    dim = 2
    u_generator = numpy.random.random((dim, dim)) + 1j * numpy.random.random(
        (dim, dim))
    u_generator = u_generator - numpy.conj(u_generator).T
    unitary = scipy.linalg.expm(u_generator)

    circuit.append(optimal_givens_decomposition(qubits[:2], unitary))

    fermion_generator = QubitOperator(()) * 0.0
    for i, j in product(range(dim), repeat=2):
        fermion_generator += jordan_wigner(
            FermionOperator(((i, 1), (j, 0)), u_generator[i, j]))

    test_unitary = scipy.linalg.expm(
        get_sparse_operator(fermion_generator, 4).toarray())
    test_final_state = test_unitary.dot(wavefunction)
    cirq_wf = simulator.simulate(circuit).final_state_vector

    assert numpy.allclose(cirq_wf, test_final_state.flatten())
def test_prepare_gaussian_state(n_qubits,
                                conserves_particle_number,
                                occupied_orbitals,
                                initial_state,
                                atol=1e-5):

    qubits = LineQubit.range(n_qubits)

    # Initialize a random quadratic Hamiltonian
    quad_ham = random_quadratic_hamiltonian(n_qubits,
                                            conserves_particle_number,
                                            real=False)
    quad_ham_sparse = get_sparse_operator(quad_ham)

    # Compute the energy of the desired state
    if occupied_orbitals is None:
        energy = quad_ham.ground_energy()
    else:
        orbital_energies, _, constant = (
            quad_ham.diagonalizing_bogoliubov_transform())
        energy = sum(orbital_energies[i] for i in occupied_orbitals) + constant

    # Get the state using a circuit simulation
    circuit = cirq.Circuit(
        prepare_gaussian_state(qubits,
                               quad_ham,
                               occupied_orbitals,
                               initial_state=initial_state))
    if isinstance(initial_state, list):
        initial_state = sum(1 << (n_qubits - 1 - i) for i in initial_state)
    state = circuit.final_state_vector(initial_state=initial_state)

    # Check that the result is an eigenstate with the correct eigenvalue
    numpy.testing.assert_allclose(quad_ham_sparse.dot(state),
                                  energy * state,
                                  atol=atol)
예제 #29
0
파일: utils.py 프로젝트: JordanovSJ/VQE
 def get_excitation_matrix(excitation_operator, n_qubits, parameter=1):
     assert parameter.imag == 0  # ?
     qubit_operator_matrix = get_sparse_operator(excitation_operator, n_qubits)
     return scipy.sparse.linalg.expm(parameter * qubit_operator_matrix)
예제 #30
0
    def ansatz_gradient(var_parameters,
                        ansatz,
                        q_system,
                        cache=None,
                        init_state_qasm=None,
                        excited_state=0):

        assert len(ansatz) == len(var_parameters)
        ansatz_statevector = QiskitSimBackend.statevector_from_ansatz(
            ansatz,
            var_parameters,
            q_system.n_orbitals,
            q_system.n_electrons,
            init_state_qasm=init_state_qasm)
        ansatz_sparse_statevector = scipy.sparse.csr_matrix(ansatz_statevector)
        H_sparse_matrix = QiskitSimBackend.ham_sparse_matrix(
            q_system, excited_state=excited_state)

        phi = ansatz_sparse_statevector.transpose().conj()
        psi = H_sparse_matrix.dot(phi)

        ansatz_grad = []

        for i in range(len(ansatz))[::-1]:
            excitations_generators = ansatz[i].excitations_generators

            excitations_generators_matrices = []
            for term in excitations_generators:
                excitations_generators_matrices.append(
                    get_sparse_operator(term, n_qubits=q_system.n_qubits))

            if len(excitations_generators_matrices) == 1:
                grad_i = 2 * (psi.transpose().conj().dot(
                    excitations_generators_matrices[0]).dot(phi)).todense()[0,
                                                                            0]

                ansatz_grad.append(grad_i.real)

                psi = scipy.sparse.linalg.expm_multiply(
                    -var_parameters[i] * excitations_generators_matrices[0],
                    psi)
                phi = scipy.sparse.linalg.expm_multiply(
                    -var_parameters[i] * excitations_generators_matrices[0],
                    phi)

            else:
                # TODO test properly
                assert len(excitations_generators_matrices) == 2

                psi = scipy.sparse.linalg.expm_multiply(
                    -var_parameters[i] * excitations_generators_matrices[1],
                    psi)
                phi = scipy.sparse.linalg.expm_multiply(
                    -var_parameters[i] * excitations_generators_matrices[1],
                    phi)

                grad_i = 2 * (psi.transpose().conj().dot(
                    excitations_generators_matrices[0] +
                    excitations_generators_matrices[1]).dot(phi)).todense()[0,
                                                                            0]

                ansatz_grad.append(grad_i.real)

                psi = scipy.sparse.linalg.expm_multiply(
                    -var_parameters[i] * excitations_generators_matrices[0],
                    psi)
                phi = scipy.sparse.linalg.expm_multiply(
                    -var_parameters[i] * excitations_generators_matrices[0],
                    phi)

        ansatz_grad = ansatz_grad[::-1]
        # print(ansatz_grad)
        return numpy.array(ansatz_grad)