def _spin_symmetric_gaussian_circuit( qubits: Sequence[cirq.QubitId], quadratic_hamiltonian: QuadraticHamiltonian, occupied_orbitals: Tuple[Sequence[int], Sequence[int]], initial_state: Union[int, Sequence[int]]) -> cirq.OP_TREE: n_qubits = len(qubits) if isinstance(initial_state, int): initially_occupied_orbitals = _occupied_orbitals( initial_state, n_qubits) else: initially_occupied_orbitals = initial_state # type: ignore for spin_sector in range(2): circuit_description, start_orbitals = ( gaussian_state_preparation_circuit( quadratic_hamiltonian, occupied_orbitals[spin_sector], spin_sector=spin_sector) ) def index_map(i): return i + spin_sector*(n_qubits // 2) spin_indices = [index_map(i) for i in range(n_qubits // 2)] spin_qubits = [qubits[i] for i in spin_indices] # Flip bits so that the correct starting orbitals are occupied yield (cirq.X(spin_qubits[j]) for j in range(n_qubits // 2) if (index_map(j) in initially_occupied_orbitals) != (index_map(j) in [index_map(k) for k in start_orbitals])) yield _ops_from_givens_rotations_circuit_description( spin_qubits, circuit_description)
def prepare_gaussian_state( qubits: Sequence[cirq.QubitId], quadratic_hamiltonian: QuadraticHamiltonian, occupied_orbitals: Sequence[int] = None, initial_state: Union[int, Sequence[int]] = 0) -> cirq.OP_TREE: """Prepare a fermionic Gaussian state from a computational basis state. A fermionic Gaussian state is an eigenstate of a quadratic Hamiltonian. If the Hamiltonian conserves particle number, then it is a Slater determinant. The algorithm used is described in arXiv:1711.05395. It assumes the Jordan-Wigner transform. Args: qubits: The qubits to which to apply the circuit. quadratic_hamiltonian: The Hamiltonian whose eigenstate is desired. occupied_orbitals: A list of integers representing the indices of the pseudoparticle orbitals to occupy in the Gaussian state. The orbitals are ordered in ascending order of energy. The default behavior is to fill the orbitals with negative energy, i.e., prepare the ground state. initial_state: The computational basis state that the qubits start in. This can be either an integer or a sequence of integers. If an integer, it is mapped to a computational basis state via "big endian" ordering of the binary representation of the integer. For example, the computational basis state on five qubits with the first and second qubits set to one is 0b11000, which is 24 in decimal. If a sequence of integers, then it contains the indices of the qubits that are set to one (indexing starts from 0). For example, the list [2, 3] represents qubits 2 and 3 being set to one. Default is 0, the all zeros state. """ n_qubits = len(qubits) circuit_description, start_orbitals = gaussian_state_preparation_circuit( quadratic_hamiltonian, occupied_orbitals) if isinstance(initial_state, int): initially_occupied_orbitals = _occupied_orbitals( initial_state, n_qubits) else: initially_occupied_orbitals = initial_state # type: ignore # Flip bits so that the correct starting orbitals are occupied yield (cirq.X(qubits[j]) for j in range(n_qubits) if (j in initially_occupied_orbitals) != (j in start_orbitals)) yield _ops_from_givens_rotations_circuit_description( qubits, circuit_description)
def _generic_gaussian_circuit( qubits: Sequence[cirq.QubitId], quadratic_hamiltonian: QuadraticHamiltonian, occupied_orbitals: Optional[Sequence[int]], initial_state: Union[int, Sequence[int]]) -> cirq.OP_TREE: n_qubits = len(qubits) circuit_description, start_orbitals = gaussian_state_preparation_circuit( quadratic_hamiltonian, occupied_orbitals) if isinstance(initial_state, int): initially_occupied_orbitals = _occupied_orbitals( initial_state, n_qubits) else: initially_occupied_orbitals = initial_state # type: ignore # Flip bits so that the correct starting orbitals are occupied yield (cirq.X(qubits[j]) for j in range(n_qubits) if (j in initially_occupied_orbitals) != (j in start_orbitals)) yield _ops_from_givens_rotations_circuit_description( qubits, circuit_description)