Ejemplo n.º 1
0
def _slater_basis_change(
        qubits: Sequence[cirq.QubitId], transformation_matrix: numpy.ndarray,
        initially_occupied_orbitals: Optional[Sequence[int]]) -> cirq.OP_TREE:
    n_qubits = len(qubits)

    if initially_occupied_orbitals is None:
        decomposition, diagonal = givens_decomposition_square(
            transformation_matrix)
        circuit_description = list(reversed(decomposition))
        # The initial state is not a computational basis state so the
        # phases left on the diagonal in the decomposition matter
        yield (cirq.Rz(rads=numpy.angle(diagonal[j])).on(qubits[j])
               for j in range(n_qubits))
    else:
        initially_occupied_orbitals = cast(Sequence[int],
                                           initially_occupied_orbitals)
        transformation_matrix = transformation_matrix[list(
            initially_occupied_orbitals)]
        n_occupied = len(initially_occupied_orbitals)
        # Flip bits so that the first n_occupied are 1 and the rest 0
        initially_occupied_orbitals_set = set(initially_occupied_orbitals)
        yield (cirq.X(qubits[j]) for j in range(n_qubits)
               if (j < n_occupied) != (j in initially_occupied_orbitals_set))
        circuit_description = slater_determinant_preparation_circuit(
            transformation_matrix)

    yield _ops_from_givens_rotations_circuit_description(
        qubits, circuit_description)
Ejemplo n.º 2
0
def prepare_slater_determinant(qubits: List[cirq.Qid],
                               slater_determinant_matrix: np.ndarray,
                               clean_ryxxy: Optional[Union[bool, int]] = True):
    """
    High level interface to the real basis rotation circuit generator

    :param qubits: List of cirq.Qids denoting logical qubits
    :param slater_determinant_matrix: basis rotation matrix
    :param clean_ryxxy: Optional[True, 1, 2, 3, 4] for indicating an error
                        model of the Givens rotation.
    :return: generator for circuit
    """
    circuit_description = slater_determinant_preparation_circuit(
        slater_determinant_matrix)
    yield (cirq.X(qubits[j])
           for j in range(slater_determinant_matrix.shape[0]))
    for parallel_ops in circuit_description:
        for op in parallel_ops:
            i, j, theta, phi = op
            if not np.isclose(phi, 0):  # testpragma: no cover
                raise ValueError("unitary must be real valued only")
            if clean_ryxxy is True or clean_ryxxy == 1:
                yield ryxxy(qubits[i], qubits[j], theta)
            elif clean_ryxxy == 2:
                yield ryxxy2(qubits[i], qubits[j], theta)
            elif clean_ryxxy == 3:
                yield ryxxy3(qubits[i], qubits[j], theta)
            elif clean_ryxxy == 4:
                yield ryxxy3(qubits[i], qubits[j], theta)
            else:
                raise ValueError("Invalide clean_ryxxy value")
def prepare_slater_determinant(qubits: Sequence[cirq.QubitId],
                               slater_determinant_matrix: numpy.ndarray,
                               initial_state: Union[int, Sequence[int]]=0
                               ) -> cirq.OP_TREE:
    r"""Prepare a Slater determinant from a computational basis state.

    A Slater determinant is described by an :math:`\eta \times N` matrix
    :math:`Q` with orthonormal rows, where :math:`\eta` is the particle number
    and :math:`N` is the total number of modes. The state corresponding to this
    matrix is

    .. math::

        b^\dagger_1 \cdots b^\dagger_{\eta} \lvert \text{vac} \rangle,

    where

    .. math::

        b^\dagger_j = \sum_{k = 1}^N Q_{jk} a^\dagger_k.

    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.
        slater_determinant_matrix: The matrix :math:`Q` which describes the
            Slater determinant to be prepared.
        initial_state: The computational basis state that the qubits start in.
            This can be either an integer or a container 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 container 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 = slater_determinant_preparation_circuit(
            slater_determinant_matrix)
    n_occupied = slater_determinant_matrix.shape[0]

    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 first n_occupied are 1 and the rest 0
    yield (cirq.X(qubits[j]) for j in range(n_qubits)
           if (j < n_occupied) != (j in initially_occupied_orbitals))

    yield _ops_from_givens_rotations_circuit_description(
            qubits, circuit_description)