Exemplo n.º 1
0
class IntegralTransformsTest(unittest.TestCase):
    def setUp(self):
        self.geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        self.basis = 'sto-3g'
        self.multiplicity = 1
        self.filename = os.path.join(DATA_DIRECTORY,
                                     'H2_sto-3g_singlet_0.7414')
        self.molecule = MolecularData(self.geometry,
                                      self.basis,
                                      self.multiplicity,
                                      filename=self.filename)
        self.molecule.load()

    def test_integrals_self_inverse(self):
        hc, hr1, hr2 = get_doci_from_integrals(
            self.molecule.one_body_integrals, self.molecule.two_body_integrals)
        proj_one_body, proj_two_body = get_projected_integrals_from_doci(
            hc, hr1, hr2)
        hc_test, hr1_test, hr2_test = get_doci_from_integrals(
            proj_one_body, proj_two_body)
        self.assertTrue(numpy.allclose(hc, hc_test))
        self.assertTrue(numpy.allclose(hr1, hr1_test))
        print(hr2)
        print(hr2_test)
        self.assertTrue(numpy.allclose(hr2, hr2_test))

    def test_integrals_to_doci(self):
        one_body_integrals = self.molecule.one_body_integrals
        two_body_integrals = self.molecule.two_body_integrals
        hc, hr1, hr2 = get_doci_from_integrals(one_body_integrals,
                                               two_body_integrals)
        self.assertEqual(hc.shape[0], 2)
        self.assertEqual(hr1.shape[0], 2)
        self.assertEqual(hr2.shape[0], 2)

        for p in range(2):
            self.assertEqual(
                hc[p] + hr2[p, p],
                2 * one_body_integrals[p, p] + two_body_integrals[p, p, p, p])
            for q in range(2):
                if p != q:
                    self.assertEqual(hr1[p, q], two_body_integrals[p, p, q, q])
                    self.assertEqual(
                        hr2[p, q], 2 * two_body_integrals[p, q, q, p] -
                        two_body_integrals[p, q, p, q])
Exemplo n.º 2
0
class MolecularDataTest(unittest.TestCase):
    def setUp(self):
        self.geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        self.basis = 'sto-3g'
        self.multiplicity = 1
        self.filename = os.path.join(DATA_DIRECTORY,
                                     'H2_sto-3g_singlet_0.7414')
        self.molecule = MolecularData(self.geometry,
                                      self.basis,
                                      self.multiplicity,
                                      filename=self.filename)
        self.molecule.load()

    def testUnitConversion(self):
        """Test the unit conversion routines"""
        unit_angstrom = 1.0
        bohr = angstroms_to_bohr(unit_angstrom)
        self.assertAlmostEqual(bohr, 1.889726)
        inverse_transform = bohr_to_angstroms(bohr)
        self.assertAlmostEqual(inverse_transform, 1.0)

    def test_name_molecule(self):
        charge = 0
        correct_name = str('H2_sto-3g_singlet_0.7414')
        computed_name = name_molecule(self.geometry,
                                      self.basis,
                                      self.multiplicity,
                                      charge,
                                      description="0.7414")
        self.assertEqual(correct_name, computed_name)
        self.assertEqual(correct_name, self.molecule.name)

        # Check (+) charge
        charge = 1
        correct_name = "H2_sto-3g_singlet_1+_0.7414"
        computed_name = name_molecule(self.geometry,
                                      self.basis,
                                      self.multiplicity,
                                      charge,
                                      description="0.7414")
        self.assertEqual(correct_name, computed_name)

        # Check > 1 atom type
        charge = 0
        correct_name = "H1-F1_sto-3g_singlet_1.0"
        test_geometry = [('H', (0, 0, 0)), ('F', (0, 0, 1.0))]
        computed_name = name_molecule(test_geometry,
                                      self.basis,
                                      self.multiplicity,
                                      charge,
                                      description="1.0")
        self.assertEqual(correct_name, computed_name)

        # Check errors in naming
        with self.assertRaises(TypeError):
            test_molecule = MolecularData(self.geometry,
                                          self.basis,
                                          self.multiplicity,
                                          description=5)
        correct_name = str('H2_sto-3g_singlet')
        test_molecule = self.molecule = MolecularData(
            self.geometry,
            self.basis,
            self.multiplicity,
            data_directory=DATA_DIRECTORY)
        self.assertSequenceEqual(correct_name, test_molecule.name)

    def test_invalid_multiplicity(self):
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        basis = 'sto-3g'
        multiplicity = -1
        with self.assertRaises(MoleculeNameError):
            MolecularData(geometry, basis, multiplicity)

    def test_geometry_from_file(self):
        water_geometry = [('O', (0., 0., 0.)), ('H', (0.757, 0.586, 0.)),
                          ('H', (-.757, 0.586, 0.))]
        filename = os.path.join(DATA_DIRECTORY, 'geometry_example.txt')
        test_geometry = geometry_from_file(filename)
        for atom in range(3):
            self.assertAlmostEqual(water_geometry[atom][0],
                                   test_geometry[atom][0])
            for coordinate in range(3):
                self.assertAlmostEqual(water_geometry[atom][1][coordinate],
                                       test_geometry[atom][1][coordinate])

    def test_save_load(self):
        n_atoms = self.molecule.n_atoms
        orbitals = self.molecule.canonical_orbitals
        self.assertFalse(orbitals is None)
        self.molecule.n_atoms += 1
        self.assertEqual(self.molecule.n_atoms, n_atoms + 1)
        self.molecule.load()
        self.assertEqual(self.molecule.n_atoms, n_atoms)
        dummy_data = self.molecule.get_from_file("dummy_entry")
        self.assertTrue(dummy_data is None)

    def test_dummy_save(self):

        # Make fake molecule.
        filename = os.path.join(DATA_DIRECTORY, 'dummy_molecule')
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        basis = '6-31g*'
        multiplicity = 7
        charge = -1
        description = 'openfermion_forever'
        molecule = MolecularData(geometry, basis, multiplicity, charge,
                                 description, filename)

        # Make some attributes to save.
        molecule.n_orbitals = 10
        molecule.n_qubits = 10
        molecule.nuclear_repulsion = -12.3
        molecule.hf_energy = 99.
        molecule.canonical_orbitals = [1, 2, 3, 4]
        molecule.orbital_energies = [5, 6, 7, 8]
        molecule.one_body_integrals = [5, 6, 7, 8]
        molecule.two_body_integrals = [5, 6, 7, 8]
        molecule.mp2_energy = -12.
        molecule.cisd_energy = 32.
        molecule.cisd_one_rdm = numpy.arange(10)
        molecule.cisd_two_rdm = numpy.arange(10)
        molecule.fci_energy = 232.
        molecule.fci_one_rdm = numpy.arange(11)
        molecule.fci_two_rdm = numpy.arange(11)
        molecule.ccsd_energy = 88.
        molecule.ccsd_single_amps = [1, 2, 3]
        molecule.ccsd_double_amps = [1, 2, 3]
        molecule.general_calculations['Fake CI'] = 1.2345
        molecule.general_calculations['Fake CI 2'] = 5.2345

        # Test missing calculation and information exceptions
        molecule.one_body_integrals = None
        with self.assertRaises(MissingCalculationError):
            molecule.get_integrals()
        molecule.hf_energy = 99.

        with self.assertRaises(ValueError):
            molecule.get_active_space_integrals([], [])

        molecule.fci_energy = None
        with self.assertRaises(MissingCalculationError):
            molecule.get_molecular_rdm(use_fci=True)
        molecule.fci_energy = 232.

        molecule.cisd_energy = None
        with self.assertRaises(MissingCalculationError):
            molecule.get_molecular_rdm(use_fci=False)
        molecule.cisd_energy = 232.

        # Save molecule.
        molecule.save()

        try:
            # Change attributes and load.
            molecule.ccsd_energy = -2.232

            # Load molecule.
            new_molecule = MolecularData(filename=filename)
            molecule.general_calculations = {}
            molecule.load()
            self.assertEqual(molecule.general_calculations['Fake CI'], 1.2345)
            # Tests re-load functionality
            molecule.save()

            # Check CCSD energy.
            self.assertAlmostEqual(new_molecule.ccsd_energy,
                                   molecule.ccsd_energy)
            self.assertAlmostEqual(molecule.ccsd_energy, 88.)
        finally:
            os.remove(filename + '.hdf5')

    def test_file_loads(self):
        """Test different filename specs"""
        data_directory = os.path.join(DATA_DIRECTORY)
        molecule = MolecularData(self.geometry,
                                 self.basis,
                                 self.multiplicity,
                                 filename=self.filename)
        test_hf_energy = molecule.hf_energy
        molecule = MolecularData(self.geometry,
                                 self.basis,
                                 self.multiplicity,
                                 filename=self.filename + ".hdf5",
                                 data_directory=data_directory)
        self.assertAlmostEqual(test_hf_energy, molecule.hf_energy)

        molecule = MolecularData(filename=self.filename + ".hdf5")
        integrals = molecule.one_body_integrals
        self.assertTrue(integrals is not None)

        with self.assertRaises(ValueError):
            MolecularData()

    def test_active_space(self):
        """Test simple active space truncation features"""

        # Start w/ no truncation
        core_const, one_body_integrals, two_body_integrals = (
            self.molecule.get_active_space_integrals(active_indices=[0, 1]))

        self.assertAlmostEqual(core_const, 0.0)
        self.assertAlmostEqual(
            scipy.linalg.norm(one_body_integrals -
                              self.molecule.one_body_integrals), 0.0)
        self.assertAlmostEqual(
            scipy.linalg.norm(two_body_integrals -
                              self.molecule.two_body_integrals), 0.0)

    def test_energies(self):
        self.assertAlmostEqual(self.molecule.hf_energy, -1.1167, places=4)
        self.assertAlmostEqual(self.molecule.mp2_energy, -1.1299, places=4)
        self.assertAlmostEqual(self.molecule.cisd_energy, -1.1373, places=4)
        self.assertAlmostEqual(self.molecule.ccsd_energy, -1.1373, places=4)
        self.assertAlmostEqual(self.molecule.ccsd_energy, -1.1373, places=4)

    def test_rdm_and_rotation(self):

        # Compute total energy from RDM.
        molecular_hamiltonian = self.molecule.get_molecular_hamiltonian()
        molecular_rdm = self.molecule.get_molecular_rdm()
        total_energy = molecular_rdm.expectation(molecular_hamiltonian)
        self.assertAlmostEqual(total_energy, self.molecule.cisd_energy)

        # Build random rotation with correction dimension.
        num_spatial_orbitals = self.molecule.n_orbitals
        rotation_generator = numpy.random.randn(num_spatial_orbitals,
                                                num_spatial_orbitals)
        rotation_matrix = scipy.linalg.expm(rotation_generator -
                                            rotation_generator.T)

        # Compute total energy from RDM under some basis set rotation.
        molecular_rdm.rotate_basis(rotation_matrix)
        molecular_hamiltonian.rotate_basis(rotation_matrix)
        total_energy = molecular_rdm.expectation(molecular_hamiltonian)
        self.assertAlmostEqual(total_energy, self.molecule.cisd_energy)

    def test_get_up_down_electrons(self):
        largest_atom = 10
        # Test first row
        correct_alpha = [0, 1, 1, 2, 2, 3, 4, 5, 5, 5, 5]
        correct_beta = [0, 0, 1, 1, 2, 2, 2, 2, 3, 4, 5]
        for n_electrons in range(1, largest_atom + 1):
            # Make molecule.
            basis = 'sto-3g'
            atom_name = periodic_table[n_electrons]
            molecule = make_atom(atom_name, basis)

            # Test.
            self.assertAlmostEqual(molecule.get_n_alpha_electrons(),
                                   correct_alpha[n_electrons])
            self.assertAlmostEqual(molecule.get_n_beta_electrons(),
                                   correct_beta[n_electrons])

    def test_abstract_molecule(self):
        """Test an abstract molecule like jellium for saving and loading"""
        jellium_interaction = get_interaction_operator(
            jellium_model(Grid(2, 2, 1.0)))
        jellium_molecule = get_molecular_data(jellium_interaction,
                                              geometry="Jellium",
                                              basis="PlaneWave22",
                                              multiplicity=1,
                                              n_electrons=4)

        jellium_filename = jellium_molecule.filename
        jellium_molecule.save()
        jellium_molecule.load()
        correct_name = "Jellium_PlaneWave22_singlet"
        self.assertEqual(jellium_molecule.name, correct_name)
        os.remove("{}.hdf5".format(jellium_filename))

    def test_load_molecular_hamiltonian(self):
        bond_length = 1.45
        geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., bond_length))]

        lih_hamiltonian = load_molecular_hamiltonian(geometry, 'sto-3g', 1,
                                                     format(bond_length), 2, 2)
        self.assertEqual(count_qubits(lih_hamiltonian), 4)

        lih_hamiltonian = load_molecular_hamiltonian(geometry, 'sto-3g', 1,
                                                     format(bond_length), 2, 3)
        self.assertEqual(count_qubits(lih_hamiltonian), 6)

        lih_hamiltonian = load_molecular_hamiltonian(geometry, 'sto-3g', 1,
                                                     format(bond_length), None,
                                                     None)
        self.assertEqual(count_qubits(lih_hamiltonian), 12)

    def test_jk_matr(self):
        h2mol = self.molecule
        j = h2mol.get_j()
        k = h2mol.get_k()
        pyscf_j = [[0.67448877, 0.6634681], [0.6634681, 0.69739377]]
        pyscf_k = [[0.67448877, 0.18128881], [0.18128881, 0.69739377]]
        for p in range(j.shape[0]):
            for q in range(j.shape[1]):
                self.assertAlmostEqual(j[p][q], pyscf_j[p][q])
                self.assertAlmostEqual(k[p][q], pyscf_k[p][q])
        ndocc = h2mol.n_electrons // 2
        E1bdy = 2 * h2mol.one_body_integrals[:ndocc, :ndocc]
        E2bdy = (2 * j[:ndocc, :ndocc]) - k[:ndocc, :ndocc]
        E_test = h2mol.nuclear_repulsion + E1bdy + E2bdy
        self.assertAlmostEqual(E_test, h2mol.hf_energy)

    def test_antisymint(self):
        h2mol = self.molecule
        antisymm_spin_orb_tei = h2mol.get_antisym()
        nocc = h2mol.n_electrons
        mol_H = h2mol.get_molecular_hamiltonian()
        E1bdy = np.sum(np.diag(mol_H.one_body_tensor[:nocc, :nocc]))
        E2bdy = 1/2.*np.einsum('ijij',\
                                 antisymm_spin_orb_tei[:nocc,:nocc,:nocc,:nocc])
        E_test = h2mol.nuclear_repulsion + E1bdy + E2bdy
        self.assertAlmostEqual(E_test, h2mol.hf_energy)

    def test_missing_calcs_for_integrals(self):
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.8764))]
        basis = 'sto-3g'
        multiplicity = 1
        molecule = MolecularData(geometry, basis, multiplicity)
        with self.assertRaises(MissingCalculationError):
            molecule.get_j()
        with self.assertRaises(MissingCalculationError):
            molecule.get_k()
        with self.assertRaises(MissingCalculationError):
            molecule.get_antisym()
Exemplo n.º 3
0
    def test_dummy_save(self):

        # Make fake molecule.
        filename = os.path.join(DATA_DIRECTORY, 'dummy_molecule')
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        basis = '6-31g*'
        multiplicity = 7
        charge = -1
        description = 'openfermion_forever'
        molecule = MolecularData(geometry, basis, multiplicity, charge,
                                 description, filename)

        # Make some attributes to save.
        molecule.n_orbitals = 10
        molecule.n_qubits = 10
        molecule.nuclear_repulsion = -12.3
        molecule.hf_energy = 99.
        molecule.canonical_orbitals = [1, 2, 3, 4]
        molecule.orbital_energies = [5, 6, 7, 8]
        molecule.one_body_integrals = [5, 6, 7, 8]
        molecule.two_body_integrals = [5, 6, 7, 8]
        molecule.mp2_energy = -12.
        molecule.cisd_energy = 32.
        molecule.cisd_one_rdm = numpy.arange(10)
        molecule.cisd_two_rdm = numpy.arange(10)
        molecule.fci_energy = 232.
        molecule.fci_one_rdm = numpy.arange(11)
        molecule.fci_two_rdm = numpy.arange(11)
        molecule.ccsd_energy = 88.
        molecule.ccsd_single_amps = [1, 2, 3]
        molecule.ccsd_double_amps = [1, 2, 3]
        molecule.general_calculations['Fake CI'] = 1.2345
        molecule.general_calculations['Fake CI 2'] = 5.2345

        # Test missing calculation and information exceptions
        molecule.one_body_integrals = None
        with self.assertRaises(MissingCalculationError):
            molecule.get_integrals()
        molecule.hf_energy = 99.

        with self.assertRaises(ValueError):
            molecule.get_active_space_integrals([], [])

        molecule.fci_energy = None
        with self.assertRaises(MissingCalculationError):
            molecule.get_molecular_rdm(use_fci=True)
        molecule.fci_energy = 232.

        molecule.cisd_energy = None
        with self.assertRaises(MissingCalculationError):
            molecule.get_molecular_rdm(use_fci=False)
        molecule.cisd_energy = 232.

        # Save molecule.
        molecule.save()

        try:
            # Change attributes and load.
            molecule.ccsd_energy = -2.232

            # Load molecule.
            new_molecule = MolecularData(filename=filename)
            molecule.general_calculations = {}
            molecule.load()
            self.assertEqual(molecule.general_calculations['Fake CI'], 1.2345)
            # Tests re-load functionality
            molecule.save()

            # Check CCSD energy.
            self.assertAlmostEqual(new_molecule.ccsd_energy,
                                   molecule.ccsd_energy)
            self.assertAlmostEqual(molecule.ccsd_energy, 88.)
        finally:
            os.remove(filename + '.hdf5')
Exemplo n.º 4
0
class IntegralTransformsTest(unittest.TestCase):
    def setUp(self):
        self.geometry = [('H', (0., 0., 0.)), ('Li', (0., 0., 1.45))]
        self.basis = 'sto-3g'
        self.multiplicity = 1
        self.filename = os.path.join(DATA_DIRECTORY,
                                     'H1-Li1_sto-3g_singlet_1.45')
        self.molecule = MolecularData(self.geometry,
                                      self.basis,
                                      self.multiplicity,
                                      filename=self.filename)
        self.molecule.load()

    def test_integrals_self_inverse(self):
        hc, hr1, hr2 = get_doci_from_integrals(
            self.molecule.one_body_integrals, self.molecule.two_body_integrals)
        doci = DOCIHamiltonian(0, hc, hr1, hr2)
        proj_one_body, proj_two_body = doci.get_projected_integrals()
        hc_test, hr1_test, hr2_test = get_doci_from_integrals(
            proj_one_body, proj_two_body)
        self.assertTrue(numpy.allclose(hc, hc_test))
        self.assertTrue(numpy.allclose(hr1, hr1_test))
        self.assertTrue(numpy.allclose(hr2, hr2_test))

    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_integrals_to_doci(self):
        one_body_integrals = self.molecule.one_body_integrals
        two_body_integrals = self.molecule.two_body_integrals
        hc, hr1, hr2 = get_doci_from_integrals(one_body_integrals,
                                               two_body_integrals)
        n_qubits = one_body_integrals.shape[0]
        self.assertEqual(hc.shape, (n_qubits, ))
        self.assertEqual(hr1.shape, (n_qubits, n_qubits))
        self.assertEqual(hr2.shape, (n_qubits, n_qubits))

        for p in range(2):
            self.assertEqual(
                hc[p] + hr2[p, p],
                2 * one_body_integrals[p, p] + two_body_integrals[p, p, p, p])
            for q in range(2):
                if p != q:
                    self.assertEqual(hr1[p, q], two_body_integrals[p, p, q, q])
                    self.assertEqual(
                        hr2[p, q], 2 * two_body_integrals[p, q, q, p] -
                        two_body_integrals[p, q, p, q])
Exemplo n.º 5
0
class DOCIHamiltonianTest(unittest.TestCase):
    def setUp(self):
        self.geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        self.basis = 'sto-3g'
        self.multiplicity = 1
        self.filename = os.path.join(DATA_DIRECTORY,
                                     'H2_sto-3g_singlet_0.7414')
        self.molecule = MolecularData(self.geometry,
                                      self.basis,
                                      self.multiplicity,
                                      filename=self.filename)
        self.molecule.load()

    def test_n_body_tensor_errors(self):
        doci_hamiltonian = DOCIHamiltonian.zero(n_qubits=2)
        with self.assertRaises(TypeError):
            doci_hamiltonian.n_body_tensors = 0
        with self.assertRaises(IndexError):
            _ = doci_hamiltonian[((0, 0), (0, 0))]
        with self.assertRaises(IndexError):
            _ = doci_hamiltonian[((0, 0), (0, 0), (0, 0), (0, 0))]
        with self.assertRaises(IndexError):
            _ = doci_hamiltonian[((1, 1), (0, 0))]
        with self.assertRaises(IndexError):
            _ = doci_hamiltonian[((0, 1), (2, 1), (3, 0), (8, 0))]

    def test_errors_operations(self):
        doci_hamiltonian = DOCIHamiltonian.zero(n_qubits=2)
        doci_hamiltonian2 = DOCIHamiltonian.zero(n_qubits=3)
        with self.assertRaises(TypeError):
            doci_hamiltonian += 'a'
        with self.assertRaises(TypeError):
            doci_hamiltonian -= 'a'
        with self.assertRaises(TypeError):
            doci_hamiltonian *= 'a'
        with self.assertRaises(TypeError):
            doci_hamiltonian /= 'a'
        with self.assertRaises(TypeError):
            doci_hamiltonian += doci_hamiltonian2
        with self.assertRaises(TypeError):
            doci_hamiltonian -= doci_hamiltonian2

    def test_adding_constants(self):
        doci_hamiltonian = DOCIHamiltonian.zero(n_qubits=2)
        doci_hamiltonian += 2
        self.assertAlmostEqual(doci_hamiltonian.constant, 2)
        doci_hamiltonian -= 3
        self.assertAlmostEqual(doci_hamiltonian.constant, -1)

    def test_basic_operations(self):
        doci_hamiltonian1 = DOCIHamiltonian.zero(n_qubits=2)
        doci_hamiltonian2 = DOCIHamiltonian.from_integrals(
            constant=self.molecule.nuclear_repulsion,
            one_body_integrals=self.molecule.one_body_integrals,
            two_body_integrals=self.molecule.two_body_integrals)
        self.assertTrue(doci_hamiltonian2 == doci_hamiltonian1 +
                        doci_hamiltonian2)
        self.assertTrue(doci_hamiltonian1 -
                        doci_hamiltonian2 == doci_hamiltonian2 / -1)
        self.assertTrue(doci_hamiltonian2 * 0 == doci_hamiltonian1)

    def test_error(self):
        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)
        with self.assertRaises(TypeError):
            doci_hamiltonian[((1, 0), (0, 1))] = 1
        with self.assertRaises(IndexError):
            _ = doci_hamiltonian[((1, 0), )]
        with self.assertRaises(IndexError):
            _ = doci_hamiltonian[((1, 1), (0, 0))]
        with self.assertRaises(IndexError):
            _ = doci_hamiltonian[((0, 1), (1, 1), (0, 0), (2, 0))]

    def test_getting_setting_constant(self):
        doci_hamiltonian = DOCIHamiltonian.zero(n_qubits=2)
        doci_hamiltonian.constant = 1
        self.assertEqual(doci_hamiltonian[()], 1)

    def test_getting_setting_1body(self):
        doci_hamiltonian = DOCIHamiltonian.zero(n_qubits=2)
        doci_hamiltonian.hc[0] = 2
        doci_hamiltonian.hc[1] = 4
        self.assertEqual(doci_hamiltonian[((0, 1), (0, 0))], 1)
        self.assertEqual(doci_hamiltonian[((1, 1), (1, 0))], 1)
        self.assertEqual(doci_hamiltonian[((2, 1), (2, 0))], 2)
        self.assertEqual(doci_hamiltonian[((3, 1), (3, 0))], 2)

    def test_getting_setting_hr2(self):
        doci_hamiltonian = DOCIHamiltonian.zero(n_qubits=2)
        doci_hamiltonian.hr2[0, 0] = 2
        doci_hamiltonian.hr2[1, 1] = 4
        self.assertEqual(doci_hamiltonian[((0, 1), (1, 1), (1, 0), (0, 0))], 1)
        self.assertEqual(doci_hamiltonian[((1, 1), (0, 1), (0, 0), (1, 0))], 1)
        self.assertEqual(doci_hamiltonian[((2, 1), (3, 1), (3, 0), (2, 0))], 2)
        self.assertEqual(doci_hamiltonian[((3, 1), (2, 1), (2, 0), (3, 0))], 2)

        doci_hamiltonian.hr2[0, 1] = 2
        self.assertEqual(doci_hamiltonian[((0, 1), (2, 1), (2, 0), (0, 0))], 1)
        self.assertEqual(doci_hamiltonian[((0, 1), (3, 1), (3, 0), (0, 0))], 1)
        self.assertEqual(doci_hamiltonian[((1, 1), (2, 1), (2, 0), (1, 0))], 1)
        self.assertEqual(doci_hamiltonian[((1, 1), (3, 1), (3, 0), (1, 0))], 1)

    def test_getting_setting_hr1(self):
        doci_hamiltonian = DOCIHamiltonian.zero(n_qubits=2)
        doci_hamiltonian.hr1[0, 1] = 2
        self.assertEqual(doci_hamiltonian[(0, 1), (1, 1), (3, 0), (2, 0)], 1)
        self.assertEqual(doci_hamiltonian[(1, 1), (0, 1), (2, 0), (3, 0)], 1)

    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))