Exemplo n.º 1
0
    def test_position_vector(self):

        # Test in 1D.
        grid = Grid(dimensions=1, length=4, scale=4.)
        test_output = [position_vector(i, grid) for i in range(grid.length)]
        correct_output = [-2, -1, 0, 1]
        self.assertEqual(correct_output, test_output)

        grid = Grid(dimensions=1, length=11, scale=2. * numpy.pi)
        for i in range(grid.length):
            self.assertAlmostEqual(-position_vector(i, grid),
                                   position_vector(grid.length - i - 1, grid))

        # Test in 2D.
        grid = Grid(dimensions=2, length=3, scale=3.)
        test_input = []
        test_output = []
        for i in range(3):
            for j in range(3):
                test_input += [(i, j)]
                test_output += [position_vector((i, j), grid)]
        correct_output = numpy.array([[-1., -1.], [-1., 0.], [-1., 1.],
                                      [0., -1.], [0., 0.], [0., 1.], [1., -1.],
                                      [1., 0.], [1., 1.]])
        self.assertAlmostEqual(0., numpy.amax(test_output - correct_output))
Exemplo n.º 2
0
 def test_properties(self):
     g = Grid(dimensions=2, length=3, scale=5.0)
     self.assertEqual(g.num_points(), 9)
     self.assertEqual(g.volume_scale(), 25)
     self.assertEqual(list(g.all_points_indices()), [
         (0, 0),
         (0, 1),
         (0, 2),
         (1, 0),
         (1, 1),
         (1, 2),
         (2, 0),
         (2, 1),
         (2, 2),
     ])
Exemplo n.º 3
0
    def test_plane_wave_hamiltonian_integration(self):
        length_set = [3, 4]
        spinless_set = [True, False]
        geometry = [('H', (0, )), ('H', (0.8, ))]
        length_scale = 1.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=True)
                h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless,
                                                      False)
                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 = numpy.amax(h_plane_wave_spectrum -
                                      h_dual_basis_spectrum)
                min_diff = numpy.amin(h_plane_wave_spectrum -
                                      h_dual_basis_spectrum)

                self.assertAlmostEqual(max_diff, 2.8372 / length_scale)
                self.assertAlmostEqual(min_diff, 2.8372 / length_scale)
Exemplo n.º 4
0
    def test_model_integration_with_constant(self):
        # Compute Hamiltonian in both momentum and position space.
        length_scale = 0.7

        grid = Grid(dimensions=2, length=3, scale=length_scale)
        spinless = True

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

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

        # Confirm momentum spectrum is shifted 2.8372 / length_scale higher.
        max_difference = numpy.amax(momentum_spectrum - position_spectrum)
        min_difference = numpy.amax(momentum_spectrum - position_spectrum)
        self.assertAlmostEqual(max_difference, 2.8372 / length_scale)
        self.assertAlmostEqual(min_difference, 2.8372 / length_scale)
Exemplo n.º 5
0
def dual_basis_jellium_hamiltonian(grid_length,
                                   dimension=3,
                                   wigner_seitz_radius=10.,
                                   n_particles=None,
                                   spinless=True):
    """Return the jellium Hamiltonian with the given parameters.

    Args:
        grid_length (int): The number of spatial orbitals per dimension.
        dimension (int): The dimension of the system.
        wigner_seitz_radius (float): The radius per particle in Bohr.
        n_particles (int): The number of particles in the system.
                           Defaults to half filling if not specified.
    """
    n_qubits = grid_length**dimension
    if not spinless:
        n_qubits *= 2

    if n_particles is None:
        # Default to half filling fraction.
        n_particles = n_qubits // 2

    if not (0 <= n_particles <= n_qubits):
        raise ValueError('n_particles must be between 0 and the number of'
                         ' spin-orbitals.')

    # Compute appropriate length scale.
    length_scale = wigner_seitz_length_scale(wigner_seitz_radius, n_particles,
                                             dimension)

    grid = Grid(dimension, grid_length, length_scale)
    hamiltonian = jellium_model(grid, spinless=spinless, plane_wave=False)
    hamiltonian = normal_ordered(hamiltonian)
    hamiltonian.compress()
    return hamiltonian
Exemplo n.º 6
0
    def test_jordan_wigner_dual_basis_jellium(self):
        # Parameters.
        grid = Grid(dimensions=2, length=3, scale=1.)
        spinless = True

        # Compute fermionic Hamiltonian. Include then subtract constant.
        fermion_hamiltonian = dual_basis_jellium_model(grid,
                                                       spinless,
                                                       include_constant=True)
        qubit_hamiltonian = jordan_wigner(fermion_hamiltonian)
        qubit_hamiltonian -= QubitOperator((), 2.8372)

        # Compute Jordan-Wigner Hamiltonian.
        test_hamiltonian = jordan_wigner_dual_basis_jellium(grid, spinless)

        # Make sure Hamiltonians are the same.
        self.assertTrue(test_hamiltonian.isclose(qubit_hamiltonian))

        # Check number of terms.
        n_qubits = count_qubits(qubit_hamiltonian)
        if spinless:
            paper_n_terms = 1 - .5 * n_qubits + 1.5 * (n_qubits**2)

        num_nonzeros = sum(1 for coeff in qubit_hamiltonian.terms.values()
                           if coeff != 0.0)
        self.assertTrue(num_nonzeros <= paper_n_terms)
Exemplo n.º 7
0
    def test_hf_state_energy_close_to_ground_energy_at_high_density(self):
        grid_length = 8
        dimension = 1
        spinless = True
        n_particles = grid_length**dimension // 2

        # High density -> small length_scale.
        length_scale = 0.25

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

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

        restricted_hamiltonian = jw_number_restrict_operator(
            hamiltonian_sparse, n_particles)

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

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

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

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

        HF_energy = expectation(hamiltonian_sparse, hf_state)

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

            self.assertLessEqual(
                HF_energy, expectation(hamiltonian_sparse, HF_competitor))
Exemplo n.º 9
0
    def test_sum_of_ordered_terms_equals_full_hamiltonian(self):
        grid_length = 4
        dimension = 2
        wigner_seitz_radius = 10.0
        inverse_filling_fraction = 2
        n_qubits = grid_length**dimension

        # Compute appropriate length scale.
        n_particles = n_qubits // inverse_filling_fraction

        # Generate the Hamiltonian.
        hamiltonian = dual_basis_jellium_hamiltonian(grid_length, dimension,
                                                     wigner_seitz_radius,
                                                     n_particles)

        terms = simulation_ordered_grouped_dual_basis_terms_with_info(
            hamiltonian)[0]
        terms_total = sum(terms, FermionOperator.zero())

        length_scale = wigner_seitz_length_scale(wigner_seitz_radius,
                                                 n_particles, dimension)

        grid = Grid(dimension, grid_length, length_scale)
        hamiltonian = jellium_model(grid, spinless=True, plane_wave=False)
        hamiltonian = normal_ordered(hamiltonian)
        self.assertTrue(terms_total.isclose(hamiltonian))
Exemplo n.º 10
0
 def test_inverse_fourier_transform_2d(self):
     grid = Grid(dimensions=2, scale=1.5, length=3)
     spinless = True
     geometry = [('H', (0, 0)), ('H', (0.5, 0.8))]
     h_plane_wave = plane_wave_hamiltonian(grid, geometry, spinless, True)
     h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless, False)
     h_dual_basis_t = inverse_fourier_transform(h_dual_basis, grid,
                                                spinless)
     self.assertTrue(
         normal_ordered(h_dual_basis_t).isclose(
             normal_ordered(h_plane_wave)))
Exemplo n.º 11
0
    def test_momentum_vector(self):
        grid = Grid(dimensions=1, length=3, scale=2. * numpy.pi)
        test_output = [momentum_vector(i, grid) for i in range(grid.length)]
        correct_output = [-1., 0, 1.]
        self.assertEqual(correct_output, test_output)

        grid = Grid(dimensions=1, length=11, scale=2. * numpy.pi)
        for i in range(grid.length):
            self.assertAlmostEqual(-momentum_vector(i, grid),
                                   momentum_vector(grid.length - i - 1, grid))

        # Test in 2D.
        grid = Grid(dimensions=2, length=3, scale=2. * numpy.pi)
        test_input = []
        test_output = []
        for i in range(3):
            for j in range(3):
                test_input += [(i, j)]
                test_output += [momentum_vector((i, j), grid)]
        correct_output = numpy.array([[-1, -1], [-1, 0], [-1, 1], [0, -1],
                                      [0, 0], [0, 1], [1, -1], [1, 0], [1, 1]])
        self.assertAlmostEqual(0., numpy.amax(test_output - correct_output))
Exemplo n.º 12
0
    def test_preconditions(self):
        nan = float('nan')

        # No exception
        _ = Grid(dimensions=0, length=0, scale=1.0)
        _ = Grid(dimensions=1, length=1, scale=1.0)
        _ = Grid(dimensions=2, length=3, scale=0.01)
        _ = Grid(dimensions=234, length=345, scale=456.0)

        with self.assertRaises(ValueError):
            _ = Grid(dimensions=1, length=1, scale=1)
        with self.assertRaises(ValueError):
            _ = Grid(dimensions=1, length=1, scale=0.0)
        with self.assertRaises(ValueError):
            _ = Grid(dimensions=1, length=1, scale=-1.0)
        with self.assertRaises(ValueError):
            _ = Grid(dimensions=1, length=1, scale=nan)

        with self.assertRaises(ValueError):
            _ = Grid(dimensions=1, length=-1, scale=1.0)
        with self.assertRaises(ValueError):
            _ = Grid(dimensions=-1, length=1, scale=1.0)
Exemplo n.º 13
0
 def test_fourier_transform(self):
     grid = Grid(dimensions=1, scale=1.5, length=3)
     spinless_set = [True, False]
     geometry = [('H', (0, )), ('H', (0.5, ))]
     for spinless in spinless_set:
         h_plane_wave = plane_wave_hamiltonian(grid, geometry, spinless,
                                               True)
         h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless,
                                               False)
         h_plane_wave_t = fourier_transform(h_plane_wave, grid, spinless)
         self.assertTrue(
             normal_ordered(h_plane_wave_t).isclose(
                 normal_ordered(h_dual_basis)))
Exemplo n.º 14
0
    def test_jordan_wigner_dual_basis_jellium_constant_shift(self):
        length_scale = 0.6
        grid = Grid(dimensions=2, length=3, scale=length_scale)
        spinless = True

        hamiltonian_without_constant = jordan_wigner_dual_basis_jellium(
            grid, spinless, include_constant=False)
        hamiltonian_with_constant = jordan_wigner_dual_basis_jellium(
            grid, spinless, include_constant=True)

        difference = hamiltonian_with_constant - hamiltonian_without_constant
        expected = FermionOperator.identity() * (2.8372 / length_scale)

        self.assertTrue(expected.isclose(difference))
Exemplo n.º 15
0
    def test_orbital_id(self):

        # Test in 1D with spin.
        grid = Grid(dimensions=1, length=5, scale=1.0)
        input_coords = [0, 1, 2, 3, 4]
        tensor_factors_up = [1, 3, 5, 7, 9]
        tensor_factors_down = [0, 2, 4, 6, 8]

        test_output_up = [orbital_id(grid, i, 1) for i in input_coords]
        test_output_down = [orbital_id(grid, i, 0) for i in input_coords]

        self.assertEqual(test_output_up, tensor_factors_up)
        self.assertEqual(test_output_down, tensor_factors_down)

        with self.assertRaises(OrbitalSpecificationError):
            orbital_id(grid, 6, 1)

        # Test in 2D without spin.
        grid = Grid(dimensions=2, length=3, scale=1.0)
        input_coords = [(0, 0), (0, 1), (1, 2)]
        tensor_factors = [0, 3, 7]
        test_output = [orbital_id(grid, i) for i in input_coords]
        self.assertEqual(test_output, tensor_factors)
Exemplo n.º 16
0
    def test_jordan_wigner_dual_basis_hamiltonian(self):
        grid = Grid(dimensions=2, length=3, scale=1.)
        spinless = True
        geometry = [('H', (0, 0)), ('H', (0.5, 0.8))]

        fermion_hamiltonian = plane_wave_hamiltonian(grid,
                                                     geometry,
                                                     spinless,
                                                     False,
                                                     include_constant=True)
        qubit_hamiltonian = jordan_wigner(fermion_hamiltonian)

        test_hamiltonian = jordan_wigner_dual_basis_hamiltonian(
            grid, geometry, spinless, include_constant=True)
        self.assertTrue(test_hamiltonian.isclose(qubit_hamiltonian))
Exemplo n.º 17
0
    def test_jw_restrict_jellium_ground_state_integration(self):
        n_qubits = 4
        grid = Grid(dimensions=1, length=n_qubits, scale=1.0)
        jellium_hamiltonian = jordan_wigner_sparse(
            jellium_model(grid, spinless=False))

        #  2 * n_qubits because of spin
        number_sparse = jordan_wigner_sparse(number_operator(2 * n_qubits))

        restricted_number = jw_number_restrict_operator(number_sparse, 2)
        restricted_jellium_hamiltonian = jw_number_restrict_operator(
            jellium_hamiltonian, 2)

        energy, ground_state = get_ground_state(restricted_jellium_hamiltonian)

        number_expectation = expectation(restricted_number, ground_state)
        self.assertAlmostEqual(number_expectation, 2)
Exemplo n.º 18
0
    def test_kinetic_integration(self):

        # Compute kinetic energy operator in both momentum and position space.
        grid = Grid(dimensions=2, length=2, scale=3.)
        spinless = False
        momentum_kinetic = plane_wave_kinetic(grid, spinless)
        position_kinetic = dual_basis_kinetic(grid, spinless)

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

        # Confirm spectra are the same.
        difference = numpy.amax(
            numpy.absolute(momentum_spectrum - position_spectrum))
        self.assertAlmostEqual(difference, 0.)
Exemplo n.º 19
0
    def test_potential_integration(self):

        # Compute potential energy operator in momentum and position space.
        grid = Grid(dimensions=2, length=3, scale=2.)
        spinless = 1
        momentum_potential = plane_wave_potential(grid, spinless)
        position_potential = dual_basis_potential(grid, spinless)

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

        # Confirm spectra are the same.
        difference = numpy.amax(
            numpy.absolute(momentum_spectrum - position_spectrum))
        self.assertAlmostEqual(difference, 0.)
Exemplo n.º 20
0
    def test_model_integration(self):

        # Compute Hamiltonian in both momentum and position space.
        grid = Grid(dimensions=2, length=3, scale=1.0)
        spinless = True
        momentum_hamiltonian = jellium_model(grid, spinless, True)
        position_hamiltonian = jellium_model(grid, spinless, False)

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

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

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

        length_scale = wigner_seitz_length_scale(wigner_seitz_radius,
                                                 n_particles, dimension)

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

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

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

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

        self.assertAlmostEqual(E_HF_dual, E_HF_plane_wave)
Exemplo n.º 22
0
 def test_plane_wave_hamiltonian_bad_element(self):
     grid = Grid(dimensions=3, scale=1.0, length=4)
     with self.assertRaises(ValueError):
         plane_wave_hamiltonian(grid, geometry=[('Unobtainium', (0, 0, 0))])
Exemplo n.º 23
0
 def test_jordan_wigner_dual_basis_hamiltonian_default_to_jellium(self):
     grid = Grid(dimensions=1, scale=1.0, length=4)
     self.assertTrue(
         jordan_wigner_dual_basis_hamiltonian(grid).isclose(
             jordan_wigner(jellium_model(grid, plane_wave=False))))
Exemplo n.º 24
0
 def test_jordan_wigner_dual_basis_hamiltonian_bad_element(self):
     grid = Grid(dimensions=3, scale=1.0, length=4)
     with self.assertRaises(ValueError):
         jordan_wigner_dual_basis_hamiltonian(grid,
                                              geometry=[('Unobtainium',
                                                         (0, 0, 0))])
Exemplo n.º 25
0
 def test_plane_wave_hamiltonian_default_to_jellium_with_no_geometry(self):
     grid = Grid(dimensions=1, scale=1.0, length=4)
     self.assertTrue(
         plane_wave_hamiltonian(grid).isclose(jellium_model(grid)))
Exemplo n.º 26
0
 def test_plane_wave_hamiltonian_bad_geometry(self):
     grid = Grid(dimensions=1, scale=1.0, length=4)
     with self.assertRaises(ValueError):
         plane_wave_hamiltonian(grid, geometry=[('H', (0, 0, 0))])
Exemplo n.º 27
0
    def test_coefficients(self):

        # Test that the coefficients post-JW transform are as claimed in paper.
        grid = Grid(dimensions=2, length=3, scale=2.)
        spinless = 1
        n_orbitals = grid.num_points()
        n_qubits = (2**(1 - spinless)) * n_orbitals
        volume = grid.volume_scale()

        # Kinetic operator.
        kinetic = dual_basis_kinetic(grid, spinless)
        qubit_kinetic = jordan_wigner(kinetic)

        # Potential operator.
        potential = dual_basis_potential(grid, spinless)
        qubit_potential = jordan_wigner(potential)

        # Check identity.
        identity = tuple()
        kinetic_coefficient = qubit_kinetic.terms[identity]
        potential_coefficient = qubit_potential.terms[identity]

        paper_kinetic_coefficient = 0.
        paper_potential_coefficient = 0.
        for indices in grid.all_points_indices():
            momenta = momentum_vector(indices, grid)
            paper_kinetic_coefficient += float(n_qubits) * momenta.dot(
                momenta) / float(4. * n_orbitals)

            if momenta.any():
                potential_contribution = -numpy.pi * float(n_qubits) / float(
                    2. * momenta.dot(momenta) * volume)
                paper_potential_coefficient += potential_contribution

        self.assertAlmostEqual(kinetic_coefficient, paper_kinetic_coefficient)
        self.assertAlmostEqual(potential_coefficient,
                               paper_potential_coefficient)

        # Check Zp.
        for p in range(n_qubits):
            zp = ((p, 'Z'), )
            kinetic_coefficient = qubit_kinetic.terms[zp]
            potential_coefficient = qubit_potential.terms[zp]

            paper_kinetic_coefficient = 0.
            paper_potential_coefficient = 0.
            for indices in grid.all_points_indices():
                momenta = momentum_vector(indices, grid)
                paper_kinetic_coefficient -= momenta.dot(momenta) / float(
                    4. * n_orbitals)

                if momenta.any():
                    potential_contribution = numpy.pi / float(
                        momenta.dot(momenta) * volume)
                    paper_potential_coefficient += potential_contribution

            self.assertAlmostEqual(kinetic_coefficient,
                                   paper_kinetic_coefficient)
            self.assertAlmostEqual(potential_coefficient,
                                   paper_potential_coefficient)

        # Check Zp Zq.
        if spinless:
            spins = [None]
        else:
            spins = [0, 1]

        for indices_a in grid.all_points_indices():
            for indices_b in grid.all_points_indices():

                paper_kinetic_coefficient = 0.
                paper_potential_coefficient = 0.

                position_a = position_vector(indices_a, grid)
                position_b = position_vector(indices_b, grid)
                differences = position_b - position_a

                for spin_a in spins:
                    for spin_b in spins:

                        p = orbital_id(grid, indices_a, spin_a)
                        q = orbital_id(grid, indices_b, spin_b)

                        if p == q:
                            continue

                        zpzq = ((min(p, q), 'Z'), (max(p, q), 'Z'))
                        if zpzq in qubit_potential.terms:
                            potential_coefficient = qubit_potential.terms[zpzq]

                        for indices_c in grid.all_points_indices():
                            momenta = momentum_vector(indices_c, grid)

                            if momenta.any():
                                potential_contribution = numpy.pi * numpy.cos(
                                    differences.dot(momenta)) / float(
                                        momenta.dot(momenta) * volume)
                                paper_potential_coefficient += (
                                    potential_contribution)

                        self.assertAlmostEqual(potential_coefficient,
                                               paper_potential_coefficient)