def setUp(self):
        self.n_qubits = 5
        self.constant = 1.7
        self.chemical_potential = 2.

        # Obtain random Hermitian and antisymmetric matrices
        self.hermitian_mat = random_hermitian_matrix(self.n_qubits)
        self.antisymmetric_mat = random_antisymmetric_matrix(self.n_qubits)

        self.combined_hermitian = (
            self.hermitian_mat -
            self.chemical_potential * numpy.eye(self.n_qubits))

        # Initialize a particle-number-conserving Hamiltonian
        self.quad_ham_pc = QuadraticHamiltonian(self.hermitian_mat,
                                                constant=self.constant)

        # Initialize a non-particle-number-conserving Hamiltonian
        self.quad_ham_npc = QuadraticHamiltonian(self.hermitian_mat,
                                                 self.antisymmetric_mat,
                                                 self.constant,
                                                 self.chemical_potential)

        # Initialize the sparse operators and get their ground energies
        self.quad_ham_pc_sparse = get_sparse_operator(self.quad_ham_pc)
        self.quad_ham_npc_sparse = get_sparse_operator(self.quad_ham_npc)

        self.pc_ground_energy, self.pc_ground_state = get_ground_state(
            self.quad_ham_pc_sparse)
        self.npc_ground_energy, self.npc_ground_state = get_ground_state(
            self.quad_ham_npc_sparse)
    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)
    def test_ground_state_particle_nonconserving(self):
        """Test getting the ground state preparation circuit for a Hamiltonian
        that does not conserve particle number."""
        for n_qubits in self.n_qubits_range:
            # Initialize a particle-number-conserving Hamiltonian
            quadratic_hamiltonian = random_quadratic_hamiltonian(
                n_qubits, False, True)

            # Compute the true ground state
            sparse_operator = get_sparse_operator(quadratic_hamiltonian)
            ground_energy, _ = get_ground_state(sparse_operator)

            # Obtain the circuit
            circuit_description, start_orbitals = (
                gaussian_state_preparation_circuit(quadratic_hamiltonian))

            # Initialize the starting state
            state = jw_configuration_state(start_orbitals, n_qubits)

            # Apply the circuit
            particle_hole_transformation = (
                jw_sparse_particle_hole_transformation_last_mode(n_qubits))
            for parallel_ops in circuit_description:
                for op in parallel_ops:
                    if op == 'pht':
                        state = particle_hole_transformation.dot(state)
                    else:
                        i, j, theta, phi = op
                        state = jw_sparse_givens_rotation(
                            i, j, theta, phi, n_qubits).dot(state)

            # Check that the state obtained using the circuit is a ground state
            difference = sparse_operator * state - ground_energy * state
            discrepancy = numpy.amax(numpy.abs(difference))
            self.assertAlmostEqual(discrepancy, 0)
    def test_excited_state_particle_nonconserving(self):
        """Test getting an excited state of a Hamiltonian that conserves
        particle number."""
        for n_qubits in self.n_qubits_range:
            # Initialize a non-particle-number-conserving Hamiltonian
            quadratic_hamiltonian = random_quadratic_hamiltonian(
                n_qubits, False)

            # Pick some orbitals to occupy
            num_occupied_orbitals = numpy.random.randint(1, n_qubits + 1)
            occupied_orbitals = numpy.random.choice(range(n_qubits),
                                                    num_occupied_orbitals,
                                                    False)

            # Compute the Gaussian state
            circuit_energy, gaussian_state = jw_get_gaussian_state(
                quadratic_hamiltonian, occupied_orbitals)

            # Compute the true energy
            orbital_energies, constant = (
                quadratic_hamiltonian.orbital_energies())
            energy = numpy.sum(orbital_energies[occupied_orbitals]) + constant

            # Check that the energies match
            self.assertAlmostEqual(energy, circuit_energy)

            # Check that the state obtained using the circuit is an eigenstate
            # with the correct eigenvalue
            sparse_operator = get_sparse_operator(quadratic_hamiltonian)
            difference = (sparse_operator * gaussian_state -
                          energy * gaussian_state)
            discrepancy = numpy.amax(numpy.abs(difference))
            self.assertAlmostEqual(discrepancy, 0)
    def setUp(self):
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        basis = 'sto-3g'
        multiplicity = 1
        filename = os.path.join(THIS_DIRECTORY, 'data',
                                '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)
    def test_particle_conserving(self):
        for n_qubits in self.n_qubits_range:
            # Initialize a particle-number-conserving Hamiltonian
            quadratic_hamiltonian = random_quadratic_hamiltonian(
                n_qubits, True)
            sparse_operator = get_sparse_operator(quadratic_hamiltonian)

            # Diagonalize the Hamiltonian using the circuit
            circuit_description = reversed(
                quadratic_hamiltonian.diagonalizing_circuit())

            for parallel_ops in circuit_description:
                for op in parallel_ops:
                    i, j, theta, phi = op
                    gate = jw_sparse_givens_rotation(i, j, theta, phi,
                                                     n_qubits)
                    sparse_operator = (
                        gate.getH().dot(sparse_operator).dot(gate))

            # Check that the result is diagonal
            diag = scipy.sparse.diags(sparse_operator.diagonal())
            difference = sparse_operator - diag
            discrepancy = 0.
            if difference.nnz:
                discrepancy = max(abs(difference.data))
            numpy.testing.assert_allclose(discrepancy, 0.0, atol=1e-7)

            # Check that the eigenvalues are in the expected order
            orbital_energies, constant = (
                quadratic_hamiltonian.orbital_energies())
            for index in range(2**n_qubits):
                bitstring = bin(index)[2:].zfill(n_qubits)
                subset = [j for j in range(n_qubits) if bitstring[j] == '1']
                energy = sum([orbital_energies[j] for j in subset]) + constant
                self.assertAlmostEqual(sparse_operator[index, index], energy)
예제 #7
0
def eigenspectrum(operator, n_qubits=None):
    """Compute the eigenspectrum of an operator.

    WARNING: This function has cubic runtime in dimension of
        Hilbert space operator, which might be exponential.

    NOTE: This function does not currently support
        QuadOperator and BosonOperator.

    Args:
        operator: QubitOperator, InteractionOperator, FermionOperator,
            PolynomialTensor, or InteractionRDM.
        n_qubits (int): number of qubits/modes in operator. if None, will
            be counted.

    Returns:
        spectrum: dense numpy array of floats giving eigenspectrum.
    """
    if isinstance(operator, (QuadOperator, BosonOperator)):
        raise TypeError('Operator of invalid type.')
    from openfermion.linalg.sparse_tools import (get_sparse_operator,
                                                 sparse_eigenspectrum)
    sparse_operator = get_sparse_operator(operator, n_qubits)
    spectrum = sparse_eigenspectrum(sparse_operator)
    return spectrum
예제 #8
0
 def test_error_operator_xyz(self):
     terms = [QubitOperator('X1'), QubitOperator('Y1'), QubitOperator('Z1')]
     expected = numpy.array([[-2. / 3, 1. / 3 + 1.j / 6, 0., 0.],
                             [1. / 3 - 1.j / 6, 2. / 3, 0., 0.],
                             [0., 0., -2. / 3, 1. / 3 + 1.j / 6],
                             [0., 0., 1. / 3 - 1.j / 6, 2. / 3]])
     sparse_op = get_sparse_operator(error_operator(terms))
     matrix = sparse_op.todense()
     self.assertTrue(numpy.allclose(matrix, expected),
                     ("Got " + str(matrix)))
예제 #9
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)
예제 #10
0
    def test_hubbard_reduce_symmetry_qubits(self):
        for i in range(4):
            n_sites = i + 2
            n_ferm = n_sites
            hub_hamil, n_orb = set_1D_hubbard(n_sites)

            # Use test function to reduce the qubits.
            hub_qbt = (symmetry_conserving_bravyi_kitaev(
                hub_hamil, n_orb, n_ferm))

            sparse_op = get_sparse_operator(hub_hamil)
            ground_energy, _ = jw_get_ground_state_at_particle_number(
                sparse_op, n_ferm)

            self.assertAlmostEqual(eigenspectrum(hub_qbt)[0], ground_energy)
    def test_ground_state_particle_nonconserving(self):
        """Test getting the ground state of a Hamiltonian that does not
        conserve particle number."""
        for n_qubits in self.n_qubits_range:
            # Initialize a non-particle-number-conserving Hamiltonian
            quadratic_hamiltonian = random_quadratic_hamiltonian(
                n_qubits, False)

            # Compute the true ground state
            sparse_operator = get_sparse_operator(quadratic_hamiltonian)
            ground_energy, _ = get_ground_state(sparse_operator)

            # Compute the ground state using the circuit
            circuit_energy, circuit_state = (
                jw_get_gaussian_state(quadratic_hamiltonian))

            # Check that the energies match
            self.assertAlmostEqual(ground_energy, circuit_energy)

            # Check that the state obtained using the circuit is a ground state
            difference = (sparse_operator * circuit_state -
                          ground_energy * circuit_state)
            discrepancy = numpy.amax(numpy.abs(difference))
            self.assertAlmostEqual(discrepancy, 0)
예제 #12
0
    def test_ucc_h2_singlet(self):
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        basis = 'sto-3g'
        multiplicity = 1
        filename = os.path.join(THIS_DIRECTORY, 'data',
                                '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)
        # Test UCCSD for accuracy against FCI using loaded t amplitudes.
        ucc_operator = uccsd_generator(self.molecule.ccsd_single_amps,
                                       self.molecule.ccsd_double_amps)

        hf_state = jw_hartree_fock_state(self.molecule.n_electrons,
                                         count_qubits(self.qubit_hamiltonian))
        uccsd_sparse = jordan_wigner_sparse(ucc_operator)
        uccsd_state = scipy.sparse.linalg.expm_multiply(uccsd_sparse, hf_state)
        expected_uccsd_energy = expectation(self.hamiltonian_matrix,
                                            uccsd_state)
        self.assertAlmostEqual(expected_uccsd_energy,
                               self.molecule.fci_energy,
                               places=4)
        print("UCCSD ENERGY: {}".format(expected_uccsd_energy))

        # Test CCSD singlet for precise match against FCI using loaded t
        # amplitudes
        packed_amplitudes = uccsd_singlet_get_packed_amplitudes(
            self.molecule.ccsd_single_amps, self.molecule.ccsd_double_amps,
            self.molecule.n_qubits, self.molecule.n_electrons)
        ccsd_operator = uccsd_singlet_generator(packed_amplitudes,
                                                self.molecule.n_qubits,
                                                self.molecule.n_electrons,
                                                anti_hermitian=False)

        ccsd_sparse_r = jordan_wigner_sparse(ccsd_operator)
        ccsd_sparse_l = jordan_wigner_sparse(
            -hermitian_conjugated(ccsd_operator))

        ccsd_state_r = scipy.sparse.linalg.expm_multiply(
            ccsd_sparse_r, hf_state)
        ccsd_state_l = scipy.sparse.linalg.expm_multiply(
            ccsd_sparse_l, hf_state)
        expected_ccsd_energy = ccsd_state_l.conjugate().dot(
            self.hamiltonian_matrix.dot(ccsd_state_r))
        self.assertAlmostEqual(expected_ccsd_energy, self.molecule.fci_energy)