Example #1
0
    def test_consistency(self):
        """Test consistency with JW for FermionOperators."""
        # Random interaction operator
        n_qubits = 5
        iop = random_interaction_operator(n_qubits, real=False)
        op1 = jordan_wigner(iop)
        op2 = jordan_wigner(get_fermion_operator(iop))

        self.assertEqual(op1, op2)

        # Interaction operator from molecule
        geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))]
        basis = 'sto-3g'
        multiplicity = 1

        filename = os.path.join(DATA_DIRECTORY, 'H1-Li1_sto-3g_singlet_1.45')
        molecule = MolecularData(geometry,
                                 basis,
                                 multiplicity,
                                 filename=filename)
        molecule.load()

        iop = molecule.get_molecular_hamiltonian()
        op1 = jordan_wigner(iop)
        op2 = jordan_wigner(get_fermion_operator(iop))

        self.assertEqual(op1, op2)
def lih_hamiltonian():
    """
    Generate test Hamiltonian from LiH.

    Args:
        None

    Return:

        hamiltonian: FermionicOperator

        spectrum: List of energies.
    """
    geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))]
    active_space_start = 1
    active_space_stop = 3
    molecule = MolecularData(geometry, 'sto-3g', 1, description="1.45")
    molecule.load()

    molecular_hamiltonian = molecule.get_molecular_hamiltonian(
        occupied_indices=range(active_space_start),
        active_indices=range(active_space_start, active_space_stop))

    hamiltonian = get_fermion_operator(molecular_hamiltonian)
    spectrum = eigenspectrum(hamiltonian)

    return hamiltonian, spectrum
Example #3
0
    def make_molecule(self, *args, **kwargs) -> MolecularData:
        """Creates a molecule in openfermion format by running psi4 and extracting the data
        Will check for previous outputfiles before running
        Will not recompute if a file was found

        Parameters
        ----------
        parameters :
            An instance of ParametersQC, which also holds an instance of ParametersPsi4 via parameters.psi4
            The molecule will be saved in parameters.filename, if this file exists before the call the molecule will be imported from the file

        Returns
        -------
        type
            the molecule in openfermion.MolecularData format

        """
        molecule = MolecularData(**self.parameters.molecular_data_param)
        # try to load

        do_compute = True
        try:
            import os
            if os.path.exists(self.parameters.filename):
                molecule.load()
                do_compute = False
        except OSError:
            do_compute = True

        if do_compute:
            molecule = self.do_make_molecule(*args, **kwargs)

        molecule.save()
        return molecule
Example #4
0
def plot_data(bond_lengths, data):
    basis = 'sto-3g'
    multiplicity = 1
    bond_length_interval = 0.1
    n_points = 25

    # Generate molecule at different bond lengths.
    hf_energies = []
    fci_energies = []

    for bond_length in bond_lengths:
        description = str(round(bond_length, 2))
        #    print(description)
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., bond_length))]
        molecule = MolecularData(geometry,
                                 basis,
                                 multiplicity,
                                 description=description)

        # Load data.
        molecule.load()

        hf_energies += [molecule.hf_energy]
        fci_energies += [molecule.fci_energy]

    plt.figure(0)
    plt.plot(bond_lengths, fci_energies, 'x-')
    plt.plot(bond_lengths, [e for e, _ in data], 'o-')
    plt.ylabel('Energy in Hartree')
    plt.xlabel('Bond length in angstrom')
    plt.show()
Example #5
0
def get_single_two_body_file(molecule_file_name):
    """
    Loads the molecule from a file.

    :param molecule_file_name: Filename
    :return: Molecule
    """
    molecule = MolecularData(filename=molecule_file_name)
    molecule.load()
    # _molecule = run_pyscf(molecule)

    return molecule.one_body_integrals, molecule.two_body_integrals
class InteractionRDMTest(unittest.TestCase):
    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()
        self.cisd_energy = self.molecule.cisd_energy
        self.rdm = self.molecule.get_molecular_rdm()
        self.hamiltonian = self.molecule.get_molecular_hamiltonian()

    def test_get_qubit_expectations(self):
        qubit_operator = jordan_wigner(self.hamiltonian)
        qubit_expectations = self.rdm.get_qubit_expectations(qubit_operator)

        test_energy = 0.0
        for qubit_term in qubit_expectations.terms:
            term_coefficient = qubit_operator.terms[qubit_term]
            test_energy += (term_coefficient *
                            qubit_expectations.terms[qubit_term])
        self.assertLess(abs(test_energy - self.cisd_energy), EQ_TOLERANCE)

    def test_get_qubit_expectations_nonmolecular_term(self):
        with self.assertRaises(InteractionRDMError):
            self.rdm.get_qubit_expectations(QubitOperator('X1 X2 X3 X4 Y6'))

    def test_get_qubit_expectations_through_expectation_method(self):
        qubit_operator = jordan_wigner(self.hamiltonian)
        test_energy = self.rdm.expectation(qubit_operator)

        self.assertLess(abs(test_energy - self.cisd_energy), EQ_TOLERANCE)

    def test_get_molecular_operator_expectation(self):
        expectation = self.rdm.expectation(self.hamiltonian)
        self.assertAlmostEqual(expectation, self.cisd_energy, places=7)

    def test_expectation_bad_type(self):
        with self.assertRaises(InteractionRDMError):
            self.rdm.expectation(12)

    def test_addition(self):
        rdm2 = self.rdm + self.rdm
        self.assertTrue(
            numpy.array_equal(rdm2.one_body_tensor,
                              rdm2.n_body_tensors[(1, 0)]))
        self.assertTrue(
            numpy.array_equal(rdm2.two_body_tensor,
                              rdm2.n_body_tensors[(1, 1, 0, 0)]))
Example #7
0
def lih_hamiltonian():
    geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))]
    active_space_start = 1
    active_space_stop = 3
    molecule = MolecularData(geometry, 'sto-3g', 1, description="1.45")
    molecule.load()
    molecular_hamiltonian = molecule.get_molecular_hamiltonian(
        occupied_indices=range(active_space_start),
        active_indices=range(active_space_start, active_space_stop))
    hamiltonian = get_fermion_operator(molecular_hamiltonian)
    ground_state_energy = eigenspectrum(hamiltonian)[0]
    return hamiltonian, ground_state_energy
def LiH_sto3g():
    """ Generates the Hamiltonian for LiH in
        the STO-3G basis, at a distance of
        1.45 A.
    """
    geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))]
    molecule = MolecularData(geometry, 'sto-3g', 1, description="1.45")
    molecule.load()
    molecular_hamiltonian = molecule.get_molecular_hamiltonian()
    hamiltonian = get_fermion_operator(molecular_hamiltonian)
    num_electrons = molecule.n_electrons
    num_orbitals = 2 * molecule.n_orbitals

    return hamiltonian, num_orbitals, num_electrons
Example #9
0
    def setUp(self):

        # Setup.
        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')
        molecule = MolecularData(
            geometry, basis, multiplicity, filename=filename)
        molecule.load()
        self.n_fermions = molecule.n_electrons
        self.n_orbitals = molecule.n_qubits

        # Get molecular Hamiltonian.
        self.molecular_hamiltonian = molecule.get_molecular_hamiltonian()
        self.fci_rdm = molecule.get_molecular_rdm(use_fci=1)
Example #10
0
def load_and_transform(filename, orbitals, transform):
    # Load data
    print('--- Loading molecule ---')
    molecule = MolecularData(filename=filename)
    molecule.load()

    print('filename: {}'.format(molecule.filename))
    print('n_atoms: {}'.format(molecule.n_atoms))
    print('n_electrons: {}'.format(molecule.n_electrons))
    print('n_orbitals: {}'.format(molecule.n_orbitals))
    #print('Canonical Orbitals: {}'.format(molecule.canonical_orbitals))
    print('n_qubits: {}'.format(molecule.n_qubits))

    # Get the Hamiltonian in an active space.
    # Set Hamiltonian parameters.
    occupied_orbitals, active_orbitals = orbitals

    molecular_hamiltonian = molecule.get_molecular_hamiltonian(
        occupied_indices=range(occupied_orbitals),
        active_indices=range(active_orbitals))

    # Map operator to fermions and qubits.
    fermion_hamiltonian = get_fermion_operator(molecular_hamiltonian)
    #print('Fermionic Hamiltonian is:\n{}'.format(fermion_hamiltonian))

    if transform is 'JW':
        qubit_h = jordan_wigner(fermion_hamiltonian)
        qubit_h.compress()
        print('\nJordan-Wigner Hamiltonian:\n{}'.format(qubit_h))
    elif transform is 'BK':
        qubit_h = bravyi_kitaev(fermion_hamiltonian)
        qubit_h.compress()
        print('\nBravyi-Kitaev Hamiltonian is:\n{}'.format(qubit_h))
    else:
        print('ERROR: Unrecognized qubit transformation: {}'.format(transform))
        sys.exit(2)

    return qubit_h
Example #11
0
    def test_rank_reduction(self):

        # Initialize H2.
        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')
        molecule = MolecularData(geometry,
                                 basis,
                                 multiplicity,
                                 filename=filename)
        molecule.load()

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

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

        # Get chemist tensor.
        constant, one_body_coefficients, chemist_tensor = (
            get_chemist_two_body_coefficients(fermion_hamiltonian))
        n_qubits = one_body_coefficients.shape[0]

        # Rank reduce with threshold.
        errors = []
        for truncation_threshold in [1., 0.1, 0.01, 0.001]:

            # Add back one-body terms and constant.
            decomposed_operator = FermionOperator((), constant)
            for p, q in itertools.product(range(n_qubits), repeat=2):
                term = ((p, 1), (q, 0))
                coefficient = one_body_coefficients[p, q]
                decomposed_operator += FermionOperator(term, coefficient)

            # Rank reduce.
            eigenvalues, one_body_squares, trunc_error = (
                low_rank_two_body_decomposition(
                    chemist_tensor, truncation_threshold=truncation_threshold))

            # Make sure error is below truncation specification.
            self.assertTrue(trunc_error < truncation_threshold)

            # Reassemble FermionOperator.
            l_max = eigenvalues.size
            for l in range(l_max):
                one_body_operator = FermionOperator()
                for p, q in itertools.product(range(n_qubits), repeat=2):
                    term = ((p, 1), (q, 0))
                    coefficient = one_body_squares[l, p, q]
                    one_body_operator += FermionOperator(term, coefficient)
                decomposed_operator += eigenvalues[l] * (one_body_operator**2)

            # Test for consistency.
            difference = normal_ordered(decomposed_operator -
                                        fermion_hamiltonian)
            errors += [difference.induced_norm()]
            self.assertTrue(errors[-1] <= trunc_error
                            or abs(errors[-1] - trunc_error) < 1e-6)
        self.assertTrue(errors[3] <= errors[2] <= errors[1] <= errors[0])

        # Rank reduce by setting final rank.
        errors = []
        for final_rank in [4, 6, 8, 10, 12]:

            # Add back one-body terms and constant.
            decomposed_operator = FermionOperator((), constant)
            for p, q in itertools.product(range(n_qubits), repeat=2):
                term = ((p, 1), (q, 0))
                coefficient = one_body_coefficients[p, q]
                decomposed_operator += FermionOperator(term, coefficient)

            # Rank reduce.
            eigenvalues, one_body_squares, trunc_error = (
                low_rank_two_body_decomposition(chemist_tensor,
                                                final_rank=final_rank))

            # Reassemble FermionOperator.
            l_max = eigenvalues.size
            for l in range(l_max):
                one_body_operator = FermionOperator()
                for p, q in itertools.product(range(n_qubits), repeat=2):
                    term = ((p, 1), (q, 0))
                    coefficient = one_body_squares[l, p, q]
                    one_body_operator += FermionOperator(term, coefficient)
                decomposed_operator += eigenvalues[l] * (one_body_operator**2)

            # Test for consistency.
            difference = normal_ordered(decomposed_operator -
                                        fermion_hamiltonian)
            errors += [difference.induced_norm()]
        self.assertTrue(errors[3] <= errors[2] <= errors[1] <= errors[0])
Example #12
0
class bravyi_kitaev_fastTransformTest(unittest.TestCase):
    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_bad_input(self):
        with self.assertRaises(TypeError):
            _bksf.bravyi_kitaev_fast(FermionOperator())

    def test_bravyi_kitaev_fast_edgeoperator_Bi(self):
        # checking the edge operators
        edge_matrix = numpy.triu(numpy.ones((4, 4)))
        edge_matrix_indices = numpy.array(
            numpy.nonzero(
                numpy.triu(edge_matrix) - numpy.diag(numpy.diag(edge_matrix))))

        correct_operators_b0 = ((0, 'Z'), (1, 'Z'), (2, 'Z'))
        correct_operators_b1 = ((0, 'Z'), (3, 'Z'), (4, 'Z'))
        correct_operators_b2 = ((1, 'Z'), (3, 'Z'), (5, 'Z'))
        correct_operators_b3 = ((2, 'Z'), (4, 'Z'), (5, 'Z'))

        qterm_b0 = QubitOperator(correct_operators_b0, 1)
        qterm_b1 = QubitOperator(correct_operators_b1, 1)
        qterm_b2 = QubitOperator(correct_operators_b2, 1)
        qterm_b3 = QubitOperator(correct_operators_b3, 1)
        self.assertTrue(
            qterm_b0.isclose(_bksf.edge_operator_b(edge_matrix_indices, 0)))
        self.assertTrue(
            qterm_b1.isclose(_bksf.edge_operator_b(edge_matrix_indices, 1)))
        self.assertTrue(
            qterm_b2.isclose(_bksf.edge_operator_b(edge_matrix_indices, 2)))
        self.assertTrue(
            qterm_b3.isclose(_bksf.edge_operator_b(edge_matrix_indices, 3)))

    def test_bravyi_kitaev_fast_edgeoperator_Aij(self):
        # checking the edge operators
        edge_matrix = numpy.triu(numpy.ones((4, 4)))
        edge_matrix_indices = numpy.array(
            numpy.nonzero(
                numpy.triu(edge_matrix) - numpy.diag(numpy.diag(edge_matrix))))
        correct_operators_a01 = ((0, 'X'), )
        correct_operators_a02 = ((0, 'Z'), (1, 'X'))
        correct_operators_a03 = ((0, 'Z'), (1, 'Z'), (2, 'X'))
        correct_operators_a12 = ((0, 'Z'), (1, 'Z'), (3, 'X'))
        correct_operators_a13 = ((0, 'Z'), (2, 'Z'), (3, 'Z'), (4, 'X'))
        correct_operators_a23 = ((1, 'Z'), (2, 'Z'), (3, 'Z'), (4, 'Z'), (5,
                                                                          'X'))

        qterm_a01 = QubitOperator(correct_operators_a01, 1)
        qterm_a02 = QubitOperator(correct_operators_a02, 1)
        qterm_a03 = QubitOperator(correct_operators_a03, 1)
        qterm_a12 = QubitOperator(correct_operators_a12, 1)
        qterm_a13 = QubitOperator(correct_operators_a13, 1)
        qterm_a23 = QubitOperator(correct_operators_a23, 1)

        self.assertTrue(
            qterm_a01.isclose(
                _bksf.edge_operator_aij(edge_matrix_indices, 0, 1)))
        self.assertTrue(
            qterm_a02.isclose(
                _bksf.edge_operator_aij(edge_matrix_indices, 0, 2)))
        self.assertTrue(
            qterm_a03.isclose(
                _bksf.edge_operator_aij(edge_matrix_indices, 0, 3)))
        self.assertTrue(
            qterm_a12.isclose(
                _bksf.edge_operator_aij(edge_matrix_indices, 1, 2)))
        self.assertTrue(
            qterm_a13.isclose(
                _bksf.edge_operator_aij(edge_matrix_indices, 1, 3)))
        self.assertTrue(
            qterm_a23.isclose(
                _bksf.edge_operator_aij(edge_matrix_indices, 2, 3)))

    def test_bravyi_kitaev_fast_jw_number_operator(self):
        # bksf algorithm allows for even number of particles. So, compare the
        # spectrum of number operator from jordan-wigner and bksf algorithm
        # to make sure half of the jordan-wigner number operator spectrum
        # can be found in bksf number operator spectrum.
        bravyi_kitaev_fast_n = _bksf.number_operator(
            self.molecular_hamiltonian)
        jw_n = QubitOperator()
        n_qubits = count_qubits(self.molecular_hamiltonian)
        for i in range(n_qubits):
            jw_n += jordan_wigner_one_body(i, i)
        jw_eig_spec = eigenspectrum(jw_n)
        bravyi_kitaev_fast_eig_spec = eigenspectrum(bravyi_kitaev_fast_n)
        evensector = 0
        for i in range(numpy.size(jw_eig_spec)):
            if bool(
                    numpy.size(
                        numpy.where(
                            jw_eig_spec[i] == bravyi_kitaev_fast_eig_spec))):
                evensector += 1
        self.assertEqual(evensector, 2**(n_qubits - 1))

    def test_bravyi_kitaev_fast_jw_hamiltonian(self):
        # make sure half of the jordan-wigner Hamiltonian eigenspectrum can
        # be found in bksf Hamiltonian eigenspectrum.
        n_qubits = count_qubits(self.molecular_hamiltonian)
        bravyi_kitaev_fast_H = _bksf.bravyi_kitaev_fast(
            self.molecular_hamiltonian)
        jw_H = jordan_wigner(self.molecular_hamiltonian)
        bravyi_kitaev_fast_H_eig = eigenspectrum(bravyi_kitaev_fast_H)
        jw_H_eig = eigenspectrum(jw_H)
        bravyi_kitaev_fast_H_eig = bravyi_kitaev_fast_H_eig.round(5)
        jw_H_eig = jw_H_eig.round(5)
        evensector = 0
        for i in range(numpy.size(jw_H_eig)):
            if bool(
                    numpy.size(
                        numpy.where(jw_H_eig[i] == bravyi_kitaev_fast_H_eig))):
                evensector += 1
        self.assertEqual(evensector, 2**(n_qubits - 1))

    def test_bravyi_kitaev_fast_generate_fermions(self):
        # 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((64, 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_bravyi_kitaev_fast_excitation_terms(self):
        # Testing on-site and excitation terms in Hamiltonian
        constant = 0
        one_body = numpy.array([[1, 2, 0, 3], [2, 1, 2, 0], [0, 2, 1, 2.5],
                                [3, 0, 2.5, 1]])
        # No Coloumb interaction
        two_body = numpy.zeros((4, 4, 4, 4))
        molecular_hamiltonian = InteractionOperator(constant, one_body,
                                                    two_body)
        n_qubits = count_qubits(molecular_hamiltonian)
        # comparing the eigenspectrum of Hamiltonian
        bravyi_kitaev_fast_H = _bksf.bravyi_kitaev_fast(molecular_hamiltonian)
        jw_H = jordan_wigner(molecular_hamiltonian)
        bravyi_kitaev_fast_H_eig = eigenspectrum(bravyi_kitaev_fast_H)
        jw_H_eig = eigenspectrum(jw_H)
        bravyi_kitaev_fast_H_eig = bravyi_kitaev_fast_H_eig.round(5)
        jw_H_eig = jw_H_eig.round(5)
        evensector_H = 0
        for i in range(numpy.size(jw_H_eig)):
            if bool(
                    numpy.size(
                        numpy.where(jw_H_eig[i] == bravyi_kitaev_fast_H_eig))):
                evensector_H += 1

        # comparing eigenspectrum of number operator
        bravyi_kitaev_fast_n = _bksf.number_operator(molecular_hamiltonian)
        jw_n = QubitOperator()
        n_qubits = count_qubits(molecular_hamiltonian)
        for i in range(n_qubits):
            jw_n += jordan_wigner_one_body(i, i)
        jw_eig_spec = eigenspectrum(jw_n)
        bravyi_kitaev_fast_eig_spec = eigenspectrum(bravyi_kitaev_fast_n)
        evensector_n = 0
        for i in range(numpy.size(jw_eig_spec)):
            if bool(
                    numpy.size(
                        numpy.where(
                            jw_eig_spec[i] == bravyi_kitaev_fast_eig_spec))):
                evensector_n += 1
        self.assertEqual(evensector_H, 2**(n_qubits - 1))
        self.assertEqual(evensector_n, 2**(n_qubits - 1))

    def test_bravyi_kitaev_fast_number_excitation_operator(self):
        # using hydrogen Hamiltonian and introducing some number operator terms
        constant = 0
        one_body = numpy.zeros((4, 4))
        one_body[(0, 0)] = .4
        one_body[(1, 1)] = .5
        one_body[(2, 2)] = .6
        one_body[(3, 3)] = .7
        two_body = self.molecular_hamiltonian.two_body_tensor
        # initiating number operator terms for all the possible cases
        two_body[(1, 2, 3, 1)] = 0.1
        two_body[(1, 3, 2, 1)] = 0.1
        two_body[(1, 2, 1, 3)] = 0.15
        two_body[(3, 1, 2, 1)] = 0.15
        two_body[(0, 2, 2, 1)] = 0.09
        two_body[(1, 2, 2, 0)] = 0.09
        two_body[(1, 2, 3, 2)] = 0.11
        two_body[(2, 3, 2, 1)] = 0.11
        two_body[(2, 2, 2, 2)] = 0.1
        molecular_hamiltonian = InteractionOperator(constant, one_body,
                                                    two_body)
        # comparing the eigenspectrum of Hamiltonian
        n_qubits = count_qubits(molecular_hamiltonian)
        bravyi_kitaev_fast_H = _bksf.bravyi_kitaev_fast(molecular_hamiltonian)
        jw_H = jordan_wigner(molecular_hamiltonian)
        bravyi_kitaev_fast_H_eig = eigenspectrum(bravyi_kitaev_fast_H)
        jw_H_eig = eigenspectrum(jw_H)
        bravyi_kitaev_fast_H_eig = bravyi_kitaev_fast_H_eig.round(5)
        jw_H_eig = jw_H_eig.round(5)
        evensector_H = 0
        for i in range(numpy.size(jw_H_eig)):
            if bool(
                    numpy.size(
                        numpy.where(jw_H_eig[i] == bravyi_kitaev_fast_H_eig))):
                evensector_H += 1

        # comparing eigenspectrum of number operator
        bravyi_kitaev_fast_n = _bksf.number_operator(molecular_hamiltonian)
        jw_n = QubitOperator()
        n_qubits = count_qubits(molecular_hamiltonian)
        for i in range(n_qubits):
            jw_n += jordan_wigner_one_body(i, i)
        jw_eig_spec = eigenspectrum(jw_n)
        bravyi_kitaev_fast_eig_spec = eigenspectrum(bravyi_kitaev_fast_n)
        evensector_n = 0
        for i in range(numpy.size(jw_eig_spec)):
            if bool(
                    numpy.size(
                        numpy.where(
                            jw_eig_spec[i] == bravyi_kitaev_fast_eig_spec))):
                evensector_n += 1
        self.assertEqual(evensector_H, 2**(n_qubits - 1))
        self.assertEqual(evensector_n, 2**(n_qubits - 1))
Example #13
0
import scipy
import scipy.linalg

# Load saved file for LiH.
diatomic_bond_length = 1.45
geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., diatomic_bond_length))]
basis = 'sto-3g'
multiplicity = 1

# Set Hamiltonian parameters.
active_space_start = 1
active_space_stop = 3

# Generate and populate instance of MolecularData.
molecule = MolecularData(geometry, basis, multiplicity, description="1.45")
molecule.load()

# Get the Hamiltonian in an active space.
molecular_hamiltonian = molecule.get_molecular_hamiltonian(
    occupied_indices=range(active_space_start),
    active_indices=range(active_space_start, active_space_stop))

# Map operator to fermions and qubits.
fermion_hamiltonian = get_fermion_operator(molecular_hamiltonian)
qubit_hamiltonian = jordan_wigner(fermion_hamiltonian)
qubit_hamiltonian.compress()
print('The Jordan-Wigner Hamiltonian in canonical basis follows:\n{}'.format(
    qubit_hamiltonian))

# Get sparse operator and ground state energy.
sparse_hamiltonian = get_sparse_operator(qubit_hamiltonian)
Example #14
0
class UnitaryCC(unittest.TestCase):
    def test_uccsd_anti_hermitian(self):
        """Test operators are anti-Hermitian independent of inputs"""
        test_orbitals = 4

        single_amplitudes = randn(*(test_orbitals, ) * 2)
        double_amplitudes = randn(*(test_orbitals, ) * 4)

        generator = uccsd_generator(single_amplitudes, double_amplitudes)
        conj_generator = hermitian_conjugated(generator)

        self.assertEqual(generator, -1. * conj_generator)

    def test_uccsd_singlet_anti_hermitian(self):
        """Test that the singlet version is anti-Hermitian"""
        test_orbitals = 8
        test_electrons = 4

        packed_amplitude_size = uccsd_singlet_paramsize(
            test_orbitals, test_electrons)

        packed_amplitudes = randn(int(packed_amplitude_size))

        generator = uccsd_singlet_generator(packed_amplitudes, test_orbitals,
                                            test_electrons)

        conj_generator = hermitian_conjugated(generator)

        self.assertEqual(generator, -1. * conj_generator)

    def test_uccsd_singlet_symmetries(self):
        """Test that the singlet generator has the correct symmetries."""
        test_orbitals = 8
        test_electrons = 4

        packed_amplitude_size = uccsd_singlet_paramsize(
            test_orbitals, test_electrons)
        packed_amplitudes = randn(int(packed_amplitude_size))
        generator = uccsd_singlet_generator(packed_amplitudes, test_orbitals,
                                            test_electrons)

        # Construct symmetry operators
        sz = sz_operator(test_orbitals)
        s_squared = s_squared_operator(test_orbitals)

        # Check the symmetries
        comm_sz = normal_ordered(commutator(generator, sz))
        comm_s_squared = normal_ordered(commutator(generator, s_squared))
        zero = FermionOperator()

        self.assertEqual(comm_sz, zero)
        self.assertEqual(comm_s_squared, zero)

    def test_uccsd_singlet_builds(self):
        """Test specific builds of the UCCSD singlet operator"""
        # Build 1
        n_orbitals = 4
        n_electrons = 2
        n_params = uccsd_singlet_paramsize(n_orbitals, n_electrons)
        self.assertEqual(n_params, 2)

        initial_amplitudes = [1., 2.]

        generator = uccsd_singlet_generator(initial_amplitudes, n_orbitals,
                                            n_electrons)

        test_generator = (FermionOperator("2^ 0", 1.) +
                          FermionOperator("0^ 2", -1.) +
                          FermionOperator("3^ 1", 1.) +
                          FermionOperator("1^ 3", -1.) +
                          FermionOperator("2^ 0 3^ 1", 4.) +
                          FermionOperator("1^ 3 0^ 2", -4.))

        self.assertEqual(normal_ordered(test_generator),
                         normal_ordered(generator))

        # Build 2
        n_orbitals = 6
        n_electrons = 2

        n_params = uccsd_singlet_paramsize(n_orbitals, n_electrons)
        self.assertEqual(n_params, 5)

        initial_amplitudes = numpy.arange(1, n_params + 1, dtype=float)
        generator = uccsd_singlet_generator(initial_amplitudes, n_orbitals,
                                            n_electrons)

        test_generator = (
            FermionOperator("2^ 0", 1.) + FermionOperator("0^ 2", -1) +
            FermionOperator("3^ 1", 1.) + FermionOperator("1^ 3", -1.) +
            FermionOperator("4^ 0", 2.) + FermionOperator("0^ 4", -2) +
            FermionOperator("5^ 1", 2.) + FermionOperator("1^ 5", -2.) +
            FermionOperator("2^ 0 3^ 1", 6.) +
            FermionOperator("1^ 3 0^ 2", -6.) +
            FermionOperator("4^ 0 5^ 1", 8.) +
            FermionOperator("1^ 5 0^ 4", -8.) +
            FermionOperator("2^ 0 5^ 1", 5.) +
            FermionOperator("1^ 5 0^ 2", -5.) +
            FermionOperator("4^ 0 3^ 1", 5.) +
            FermionOperator("1^ 3 0^ 4", -5.) +
            FermionOperator("2^ 0 4^ 0", 5.) +
            FermionOperator("0^ 4 0^ 2", -5.) +
            FermionOperator("3^ 1 5^ 1", 5.) +
            FermionOperator("1^ 5 1^ 3", -5.))

        self.assertEqual(normal_ordered(test_generator),
                         normal_ordered(generator))

    def test_sparse_uccsd_generator_numpy_inputs(self):
        """Test numpy ndarray inputs to uccsd_generator that are sparse"""
        test_orbitals = 30
        sparse_single_amplitudes = numpy.zeros((test_orbitals, test_orbitals))
        sparse_double_amplitudes = numpy.zeros(
            (test_orbitals, test_orbitals, test_orbitals, test_orbitals))

        sparse_single_amplitudes[3, 5] = 0.12345
        sparse_single_amplitudes[12, 4] = 0.44313

        sparse_double_amplitudes[0, 12, 6, 2] = 0.3434
        sparse_double_amplitudes[1, 4, 6, 13] = -0.23423

        generator = uccsd_generator(sparse_single_amplitudes,
                                    sparse_double_amplitudes)

        test_generator = (0.12345 * FermionOperator("3^ 5") +
                          (-0.12345) * FermionOperator("5^ 3") +
                          0.44313 * FermionOperator("12^ 4") +
                          (-0.44313) * FermionOperator("4^ 12") +
                          0.3434 * FermionOperator("0^ 12 6^ 2") +
                          (-0.3434) * FermionOperator("2^ 6 12^ 0") +
                          (-0.23423) * FermionOperator("1^ 4 6^ 13") +
                          0.23423 * FermionOperator("13^ 6 4^ 1"))
        self.assertEqual(test_generator, generator)

    def test_sparse_uccsd_generator_list_inputs(self):
        """Test list inputs to uccsd_generator that are sparse"""
        sparse_single_amplitudes = [[[3, 5], 0.12345], [[12, 4], 0.44313]]
        sparse_double_amplitudes = [[[0, 12, 6, 2], 0.3434],
                                    [[1, 4, 6, 13], -0.23423]]

        generator = uccsd_generator(sparse_single_amplitudes,
                                    sparse_double_amplitudes)

        test_generator = (0.12345 * FermionOperator("3^ 5") +
                          (-0.12345) * FermionOperator("5^ 3") +
                          0.44313 * FermionOperator("12^ 4") +
                          (-0.44313) * FermionOperator("4^ 12") +
                          0.3434 * FermionOperator("0^ 12 6^ 2") +
                          (-0.3434) * FermionOperator("2^ 6 12^ 0") +
                          (-0.23423) * FermionOperator("1^ 4 6^ 13") +
                          0.23423 * FermionOperator("13^ 6 4^ 1"))
        self.assertEqual(test_generator, generator)

    def test_uccsd_singlet_get_packed_amplitudes(self):
        test_orbitals = 6
        test_electrons = 2
        sparse_single_amplitudes = numpy.zeros((test_orbitals, test_orbitals))
        sparse_double_amplitudes = numpy.zeros(
            (test_orbitals, test_orbitals, test_orbitals, test_orbitals))

        sparse_single_amplitudes[2, 0] = 0.12345
        sparse_single_amplitudes[3, 1] = 0.12345

        sparse_double_amplitudes[2, 0, 3, 1] = 0.9

        sparse_double_amplitudes[2, 0, 4, 0] = 0.3434
        sparse_double_amplitudes[5, 1, 3, 1] = 0.3434

        packed_amplitudes = uccsd_singlet_get_packed_amplitudes(
            sparse_single_amplitudes, sparse_double_amplitudes, test_orbitals,
            test_electrons)

        self.assertEqual(len(packed_amplitudes), 5)

        self.assertTrue(
            numpy.allclose(packed_amplitudes,
                           numpy.array([0.12345, 0., 0.9, 0., 0.3434])))

    def test_ucc_h2(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 for precise match against FCI using loaded t amplitudes.
        ccsd_operator = uccsd_generator(self.molecule.ccsd_single_amps,
                                        self.molecule.ccsd_double_amps,
                                        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)

    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)

    def test_value_error_for_odd_n_qubits(self):
        # Pass odd n_qubits to singlet generators
        with self.assertRaises(ValueError):
            _ = uccsd_singlet_paramsize(3, 4)

    def test_value_error_bad_amplitudes(self):
        with self.assertRaises(ValueError):
            _ = uccsd_singlet_generator([1.], 3, 4)
Example #15
0
def make_molecular_energy_obj(molecule_name,
                              basis="sto-3g",
                              geometry_info=None,
                              n_cancel_orbital=0,
                              n_frozen_orbital=0,
                              cas_irrep_nocc=None,
                              cas_irrep_ncore=None,
                              fermi_qubit_transform=bravyi_kitaev,
                              is_computed=False):
    if geometry_info == None:
        geometry_info = equilibrium_geometry_dict[molecule_name]

    # Get geometry
    if molecule_name not in geometry_generator_dict.keys():
        print("No such example molecule, using default H2 hamiltonian.")
        molecule_name = "H2"

    geometry = geometry_generator_dict[molecule_name](geometry_info)

    # Get fermion Hamiltonian

    multiplicity = 1
    charge = 0
    molecule = MolecularData(geometry, basis, multiplicity, charge,
                             str(geometry_info))
    molecule.symmetry = True
    if not is_computed:
        molecule = run_pyscf(molecule,
                             run_fci=1,
                             n_frozen_orbital=n_frozen_orbital,
                             n_cancel_orbital=n_cancel_orbital,
                             cas_irrep_nocc=cas_irrep_nocc,
                             cas_irrep_ncore=cas_irrep_ncore,
                             verbose=False)
    molecule.load()

    active_space_start = n_frozen_orbital
    active_space_stop = molecule.n_orbitals - n_cancel_orbital
    n_active_orb = active_space_stop - active_space_start
    molecule.n_orbitals = n_active_orb
    molecule.n_qubits = n_active_orb * 2
    molecule.n_electrons = molecule.n_electrons - active_space_start * 2

    fermion_hamiltonian = get_fermion_operator(
        molecule.get_molecular_hamiltonian(
            occupied_indices=molecule.frozen_orbitals,
            active_indices=molecule.active_orbitals))

    # Map ferimon Hamiltonian to qubit Hamiltonian
    qubit_hamiltonian = fermi_qubit_transform(fermion_hamiltonian)

    # qubit_electron_operator=fermi_qubit_transform(get_electron_fermion_operator(molecule.n_electrons))
    qubit_electron_operator = get_HF_operator(molecule.n_electrons,
                                              fermi_qubit_transform)
    # qubit_hamiltonian=get_dressed_operator(qubit_electron_operator,qubit_hamiltonian)

    # Ignore terms in Hamiltonian that close to zero
    qubit_hamiltonian.compress()

    # Set the terminate_energy to be achieving the chemical accuracy
    terminate_energy = molecule.fci_energy + CHEMICAL_ACCURACY
    obj_info = {
        "n_qubit": molecule.n_qubits,
        "start_cost": molecule.hf_energy,
        "terminate_cost": terminate_energy
    }

    init_operator = HartreeFockInitBlock(
        get_operator_qsubset(qubit_electron_operator))

    return EnergyObjective(qubit_hamiltonian, molecule.n_qubits, init_operator,
                           obj_info)
Example #16
0
class UnitaryCC(unittest.TestCase):
    def test_uccsd_anti_hermitian(self):
        """Test operators are anti-Hermitian independent of inputs"""
        test_orbitals = 4

        single_amplitudes = randn(*(test_orbitals, ) * 2)
        double_amplitudes = randn(*(test_orbitals, ) * 4)

        generator = uccsd_operator(single_amplitudes, double_amplitudes)
        conj_generator = hermitian_conjugated(generator)

        self.assertTrue(generator.isclose(-1. * conj_generator))

    def test_uccsd_singlet_anti_hermitian(self):
        """Test that the singlet version is anti-Hermitian"""
        test_orbitals = 8
        test_electrons = 4

        packed_amplitude_size = uccsd_singlet_paramsize(
            test_orbitals, test_electrons)

        packed_amplitudes = randn(int(packed_amplitude_size))

        generator = uccsd_singlet_operator(packed_amplitudes, test_orbitals,
                                           test_electrons)

        conj_generator = hermitian_conjugated(generator)

        self.assertTrue(generator.isclose(-1. * conj_generator))

    def test_uccsd_singlet_build(self):
        """Test a specific build of the UCCSD singlet operator"""
        initial_amplitudes = [-1.14941450e-08, 5.65340614e-02]
        n_orbitals = 4
        n_electrons = 2

        generator = uccsd_singlet_operator(initial_amplitudes, n_orbitals,
                                           n_electrons)

        test_generator = (0.0565340614 * FermionOperator("2^ 0 3^ 1") +
                          1.1494145e-08 * FermionOperator("1^ 3") +
                          0.0565340614 * FermionOperator("3^ 1 2^ 0") +
                          0.0565340614 * FermionOperator("2^ 0 2^ 0") +
                          1.1494145e-08 * FermionOperator("0^ 2") +
                          (-0.0565340614) * FermionOperator("1^ 3 0^ 2") +
                          (-1.1494145e-08) * FermionOperator("3^ 1") +
                          (-0.0565340614) * FermionOperator("1^ 3 1^ 3") +
                          (-0.0565340614) * FermionOperator("0^ 2 0^ 2") +
                          (-1.1494145e-08) * FermionOperator("2^ 0") +
                          0.0565340614 * FermionOperator("3^ 1 3^ 1") +
                          (-0.0565340614) * FermionOperator("0^ 2 1^ 3"))
        self.assertTrue(test_generator.isclose(generator))

    def test_sparse_uccsd_operator_numpy_inputs(self):
        """Test numpy ndarray inputs to uccsd_operator that are sparse"""
        test_orbitals = 30
        sparse_single_amplitudes = numpy.zeros((test_orbitals, test_orbitals))
        sparse_double_amplitudes = numpy.zeros(
            (test_orbitals, test_orbitals, test_orbitals, test_orbitals))

        sparse_single_amplitudes[3, 5] = 0.12345
        sparse_single_amplitudes[12, 4] = 0.44313

        sparse_double_amplitudes[0, 12, 6, 2] = 0.3434
        sparse_double_amplitudes[1, 4, 6, 13] = -0.23423

        generator = uccsd_operator(sparse_single_amplitudes,
                                   sparse_double_amplitudes)

        test_generator = (0.12345 * FermionOperator("3^ 5") +
                          (-0.12345) * FermionOperator("5^ 3") +
                          0.44313 * FermionOperator("12^ 4") +
                          (-0.44313) * FermionOperator("4^ 12") +
                          0.3434 * FermionOperator("0^ 12 6^ 2") +
                          (-0.3434) * FermionOperator("2^ 6 12^ 0") +
                          (-0.23423) * FermionOperator("1^ 4 6^ 13") +
                          0.23423 * FermionOperator("13^ 6 4^ 1"))
        self.assertTrue(test_generator.isclose(generator))

    def test_sparse_uccsd_operator_list_inputs(self):
        """Test list inputs to uccsd_operator that are sparse"""
        sparse_single_amplitudes = [[[3, 5], 0.12345], [[12, 4], 0.44313]]
        sparse_double_amplitudes = [[[0, 12, 6, 2], 0.3434],
                                    [[1, 4, 6, 13], -0.23423]]

        generator = uccsd_operator(sparse_single_amplitudes,
                                   sparse_double_amplitudes)

        test_generator = (0.12345 * FermionOperator("3^ 5") +
                          (-0.12345) * FermionOperator("5^ 3") +
                          0.44313 * FermionOperator("12^ 4") +
                          (-0.44313) * FermionOperator("4^ 12") +
                          0.3434 * FermionOperator("0^ 12 6^ 2") +
                          (-0.3434) * FermionOperator("2^ 6 12^ 0") +
                          (-0.23423) * FermionOperator("1^ 4 6^ 13") +
                          0.23423 * FermionOperator("13^ 6 4^ 1"))
        self.assertTrue(test_generator.isclose(generator))

    def test_ucc(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_operator(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 for precise match against FCI using loaded t amplitudes.
        ccsd_operator = uccsd_operator(self.molecule.ccsd_single_amps,
                                       self.molecule.ccsd_double_amps,
                                       anti_hermitian=False)

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

        # Test CCSD for precise match against FCI using loaded t amplitudes
        ccsd_operator = uccsd_operator(self.molecule.ccsd_single_amps,
                                       self.molecule.ccsd_double_amps,
                                       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.getH().dot(
            self.hamiltonian_matrix.dot(ccsd_state_r))[0, 0]
        self.assertAlmostEqual(expected_ccsd_energy, self.molecule.fci_energy)