def setUp(self): self.n_qubits = 5 self.constant = 1.7 self.chemical_potential = 2. # Obtain random Hermitian and antisymmetric matrices self.hermitian_mat = random_hermitian_matrix(self.n_qubits) self.antisymmetric_mat = random_antisymmetric_matrix(self.n_qubits) self.combined_hermitian = ( self.hermitian_mat - self.chemical_potential * numpy.eye(self.n_qubits)) # Initialize a particle-number-conserving Hamiltonian self.quad_ham_pc = QuadraticHamiltonian( self.constant, self.hermitian_mat) # Initialize a non-particle-number-conserving Hamiltonian self.quad_ham_npc = QuadraticHamiltonian( self.constant, self.hermitian_mat, self.antisymmetric_mat, self.chemical_potential) # Initialize the sparse operators and get their ground energies self.quad_ham_pc_sparse = get_sparse_operator(self.quad_ham_pc) self.quad_ham_npc_sparse = get_sparse_operator(self.quad_ham_npc) self.pc_ground_energy, self.pc_ground_state = get_ground_state( self.quad_ham_pc_sparse) self.npc_ground_energy, self.npc_ground_state = get_ground_state( self.quad_ham_npc_sparse)
def test_hf_state_energy_close_to_ground_energy_at_high_density(self): grid_length = 8 dimension = 1 spinless = True n_particles = grid_length**dimension // 2 # High density -> small length_scale. length_scale = 0.25 grid = Grid(dimension, grid_length, length_scale) hamiltonian = jellium_model(grid, spinless) hamiltonian_sparse = get_sparse_operator(hamiltonian) hf_state = hartree_fock_state_jellium(grid, n_particles, spinless, plane_wave=True) restricted_hamiltonian = jw_number_restrict_operator( hamiltonian_sparse, n_particles) E_g = get_ground_state(restricted_hamiltonian)[0] E_HF_plane_wave = expectation(hamiltonian_sparse, hf_state) self.assertAlmostEqual(E_g, E_HF_plane_wave, places=5)
def test_ground_state_particle_nonconserving(self): """Test getting the ground state preparation circuit for a Hamiltonian that does not conserve particle number.""" for n_qubits in self.n_qubits_range: # Initialize a particle-number-conserving Hamiltonian quadratic_hamiltonian = random_quadratic_hamiltonian( n_qubits, False, True) # Compute the true ground state sparse_operator = get_sparse_operator(quadratic_hamiltonian) ground_energy, _ = get_ground_state(sparse_operator) # Obtain the circuit circuit_description, start_orbitals = ( gaussian_state_preparation_circuit(quadratic_hamiltonian)) # Initialize the starting state state = jw_configuration_state(start_orbitals, n_qubits) # Apply the circuit particle_hole_transformation = ( jw_sparse_particle_hole_transformation_last_mode(n_qubits)) for parallel_ops in circuit_description: for op in parallel_ops: if op == 'pht': state = particle_hole_transformation.dot(state) else: i, j, theta, phi = op state = jw_sparse_givens_rotation( i, j, theta, phi, n_qubits).dot(state) # Check that the state obtained using the circuit is a ground state difference = sparse_operator * state - ground_energy * state discrepancy = numpy.amax(numpy.abs(difference)) self.assertAlmostEqual(discrepancy, 0)
def test_orbital_energies(self): """Test getting the orbital energies.""" # Test the particle-number-conserving case orbital_energies, constant = self.quad_ham_pc.orbital_energies() # Test the ground energy energy = numpy.sum( orbital_energies[orbital_energies < -EQ_TOLERANCE]) + constant quad_ham_pc_sparse = get_sparse_operator(self.quad_ham_pc) ground_energy, ground_state = get_ground_state(quad_ham_pc_sparse) self.assertAlmostEqual(energy, ground_energy) # Test the non-particle-number-conserving case orbital_energies, constant = self.quad_ham_npc.orbital_energies() # Test the ground energy energy = constant quad_ham_npc_sparse = get_sparse_operator(self.quad_ham_npc) ground_energy, ground_state = get_ground_state(quad_ham_npc_sparse) self.assertAlmostEqual(energy, ground_energy)
def test_apply_constraints(self): # Get norm of original operator. original_norm = 0. for term, coefficient in self.fermion_hamiltonian.terms.items(): if term != (): original_norm += abs(coefficient) # Get modified operator. modified_operator = apply_constraints(self.fermion_hamiltonian, self.n_fermions) modified_operator.compress() # Get norm of modified operator. modified_norm = 0. for term, coefficient in modified_operator.terms.items(): if term != (): modified_norm += abs(coefficient) self.assertTrue(modified_norm < original_norm) # Map both to sparse matrix under Jordan-Wigner. sparse_original = get_sparse_operator(self.fermion_hamiltonian) sparse_modified = get_sparse_operator(modified_operator) # Check spectra. sparse_original = jw_number_restrict_operator(sparse_original, self.n_fermions) sparse_modified = jw_number_restrict_operator(sparse_modified, self.n_fermions) original_spectrum = sparse_eigenspectrum(sparse_original) modified_spectrum = sparse_eigenspectrum(sparse_modified) spectral_deviation = numpy.amax( numpy.absolute(original_spectrum - modified_spectrum)) self.assertAlmostEqual(spectral_deviation, 0.) # Check expectation value. energy, wavefunction = get_ground_state(sparse_original) modified_energy = expectation(sparse_modified, wavefunction) self.assertAlmostEqual(modified_energy, energy) # Test consistency with cvxopt. scipy_operator = apply_constraints(self.fermion_hamiltonian, self.n_fermions, use_scipy=False) # Get norm. scipy_norm = 0. for term, coefficient in scipy_operator.terms.items(): if term != (): scipy_norm += abs(coefficient) self.assertAlmostEqual(scipy_norm, modified_norm)
def test_constraint_matrix(self): # Randomly project operator with constraints. numpy.random.seed(8) constraints = constraint_matrix(self.n_orbitals, self.n_fermions) n_constraints, n_terms = constraints.shape self.assertEqual(1 + self.n_orbitals**2 + self.n_orbitals**4, n_terms) random_weights = numpy.random.randn(n_constraints) vectorized_operator = operator_to_vector(self.fermion_hamiltonian) modification_vector = constraints.transpose() * random_weights new_operator_vector = vectorized_operator + modification_vector modified_operator = vector_to_operator(new_operator_vector, self.n_orbitals) # Map both to sparse matrix under Jordan-Wigner. sparse_original = get_sparse_operator(self.fermion_hamiltonian) sparse_modified = get_sparse_operator(modified_operator) # Check expectation value. energy, wavefunction = get_ground_state(sparse_original) modified_energy = expectation(sparse_modified, wavefunction) self.assertAlmostEqual(modified_energy, energy)
def energy_levels(separation): g = [('H', (0., 0., 0.)), ('H', (0., 0., separation))] d = str(separation) m = MolecularData(g, basis, multiplicity, description=d, data_directory=data_directory) run_psi4(m, run_fci=True, delete_output=True) _, s = get_ground_state( get_sparse_operator( normal_ordered( get_fermion_operator( m.get_molecular_hamiltonian( active_indices=range(active_spatial_orbitals)))))) h = normal_ordered( get_fermion_operator( m.get_molecular_hamiltonian( active_indices=range(active_spatial_orbitals + virtual_spatial_orbitals)))) o = vqse_operators(s) return generalized_eigenvalues(h_matrix(h, o, s), s_matrix(o, s))
# 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) energy, state = get_ground_state(sparse_hamiltonian) print('Ground state energy before rotation is {} Hartree.\n'.format(energy)) # Randomly rotate. n_orbitals = molecular_hamiltonian.n_qubits // 2 n_variables = int(n_orbitals * (n_orbitals - 1) / 2) random_angles = numpy.pi * (1. - 2. * numpy.random.rand(n_variables)) kappa = numpy.zeros((n_orbitals, n_orbitals)) index = 0 for p in range(n_orbitals): for q in range(p + 1, n_orbitals): kappa[p, q] = random_angles[index] kappa[q, p] = -numpy.conjugate(random_angles[index]) index += 1 # Build the unitary rotation matrix.
from openfermion.hamiltonians import fermi_hubbard from openfermion.transforms import get_sparse_operator, jordan_wigner from openfermion.utils import get_ground_state # Set model. x_dimension = 2 y_dimension = 2 tunneling = 2. coulomb = 1. magnetic_field = 0.5 chemical_potential = 0.25 periodic = 1 spinless = 1 # Get fermion operator. hubbard_model = fermi_hubbard( x_dimension, y_dimension, tunneling, coulomb, chemical_potential, magnetic_field, periodic, spinless) print (hubbard_model) # Get qubit operator under Jordan-Wigner. jw_hamiltonian = jordan_wigner(hubbard_model) jw_hamiltonian.compress() print (jw_hamiltonian) # Get scipy.sparse.csc representation. sparse_operator = get_sparse_operator(hubbard_model) print (sparse_operator) print ('\nEnergy of the model is {} in units of T and J.'.format( get_ground_state(sparse_operator)[0]))