def test_spin_symmetric_bogoliubov_transform( n_spatial_orbitals, conserves_particle_number, atol=5e-5): n_qubits = 2*n_spatial_orbitals qubits = LineQubit.range(n_qubits) # Initialize a random quadratic Hamiltonian quad_ham = random_quadratic_hamiltonian( n_spatial_orbitals, conserves_particle_number, real=True, expand_spin=True, seed=28166) # Reorder the Hamiltonian and get sparse matrix quad_ham = openfermion.get_quadratic_hamiltonian( openfermion.reorder( openfermion.get_fermion_operator(quad_ham), openfermion.up_then_down) ) quad_ham_sparse = get_sparse_operator(quad_ham) # Compute the orbital energies and transformation_matrix up_orbital_energies, _, _ = ( quad_ham.diagonalizing_bogoliubov_transform(spin_sector=0)) down_orbital_energies, _, _ = ( quad_ham.diagonalizing_bogoliubov_transform(spin_sector=1)) _, transformation_matrix, _ = ( quad_ham.diagonalizing_bogoliubov_transform()) # Pick some orbitals to occupy up_orbitals = list(range(2)) down_orbitals = [0, 2, 3] energy = sum(up_orbital_energies[up_orbitals]) + sum( down_orbital_energies[down_orbitals]) + quad_ham.constant # Construct initial state initial_state = ( sum(2**(n_qubits - 1 - int(i)) for i in up_orbitals) + sum(2**(n_qubits - 1 - int(i+n_spatial_orbitals)) for i in down_orbitals) ) # Apply the circuit circuit = cirq.Circuit.from_ops( bogoliubov_transform( qubits, transformation_matrix, initial_state=initial_state)) state = circuit.apply_unitary_effect_to_state(initial_state) # Check that the result is an eigenstate with the correct eigenvalue numpy.testing.assert_allclose( quad_ham_sparse.dot(state), energy * state, atol=atol)
def test_prepare_gaussian_state_with_spin_symmetry(n_spatial_orbitals, conserves_particle_number, occupied_orbitals, initial_state, atol=1e-5): n_qubits = 2 * n_spatial_orbitals qubits = LineQubit.range(n_qubits) # Initialize a random quadratic Hamiltonian quad_ham = random_quadratic_hamiltonian( n_spatial_orbitals, conserves_particle_number, real=True, expand_spin=True, seed=639) # Reorder the Hamiltonian and get sparse matrix quad_ham = openfermion.get_quadratic_hamiltonian( openfermion.reorder( openfermion.get_fermion_operator(quad_ham), openfermion.up_then_down) ) quad_ham_sparse = get_sparse_operator(quad_ham) # Compute the energy of the desired state energy = 0.0 for spin_sector in range(2): orbital_energies, _, _ = ( quad_ham.diagonalizing_bogoliubov_transform( spin_sector=spin_sector) ) energy += sum(orbital_energies[i] for i in occupied_orbitals[spin_sector]) energy += quad_ham.constant # Get the state using a circuit simulation circuit = cirq.Circuit.from_ops( prepare_gaussian_state( qubits, quad_ham, occupied_orbitals, initial_state=initial_state)) if isinstance(initial_state, list): initial_state = sum(1 << (n_qubits - 1 - i) for i in initial_state) state = circuit.apply_unitary_effect_to_state(initial_state) # Check that the result is an eigenstate with the correct eigenvalue numpy.testing.assert_allclose( quad_ham_sparse.dot(state), energy * state, atol=atol)