Ejemplo n.º 1
0
def hartree_fock_bitstring_mapped(
    num_spin_orbitals: int,
    num_particles: Tuple[int, int],
    qubit_converter: QubitConverter,
    match_convert: bool = True,
) -> List[bool]:
    """Compute the bitstring representing the mapped Hartree-Fock state for the specified system.

    Args:
        num_spin_orbitals: The number of spin orbitals, has a min. value of 1.
        num_particles: The number of particles as a tuple (alpha, beta) containing the number of
            alpha- and  beta-spin electrons, respectively.
        qubit_converter: A QubitConverter instance.
        match_convert: Whether to use `convert_match` method of the qubit converter (default),
            or just do mapping and possibly two qubit reduction but no tapering. The latter
            is an advanced usage - e.g. if we are trying to auto-select the tapering sector
            then we would not want any match conversion done on a converter that was set to taper.

    Returns:
        The bitstring representing the mapped state of the Hartree-Fock state as array of bools.
    """

    # get the bitstring encoding the Hartree Fock state
    bitstr = hartree_fock_bitstring(num_spin_orbitals, num_particles)

    # encode the bitstring as a `FermionicOp`
    label = ["+" if bit else "I" for bit in bitstr]
    bitstr_op = FermionicOp("".join(label), display_format="sparse")

    # map the `FermionicOp` to a qubit operator
    qubit_op: PauliSumOp = (
        qubit_converter.convert_match(bitstr_op, check_commutes=False)
        if match_convert
        else qubit_converter.convert_only(bitstr_op, num_particles)
    )

    # We check the mapped operator `x` part of the paulis because we want to have particles
    # i.e. True, where the initial state introduced a creation (`+`) operator.
    bits = []
    for bit in qubit_op.primitive.paulis.x[0]:
        bits.append(bit)

    return bits
Ejemplo n.º 2
0
def _build_single_hopping_operator(
    excitation: Tuple[Tuple[int, ...], Tuple[int, ...]],
    num_spin_orbitals: int,
    qubit_converter: QubitConverter,
) -> Tuple[PauliSumOp, List[bool]]:
    label = ["I"] * num_spin_orbitals
    for occ in excitation[0]:
        label[occ] = "+"
    for unocc in excitation[1]:
        label[unocc] = "-"
    fer_op = FermionicOp(("".join(label), 4.0**len(excitation[0])),
                         display_format="sparse")

    qubit_op: PauliSumOp = qubit_converter.convert_only(
        fer_op, qubit_converter.num_particles)
    z2_symmetries = qubit_converter.z2symmetries

    commutativities = []
    if not z2_symmetries.is_empty():
        for symmetry in z2_symmetries.symmetries:
            symmetry_op = PauliSumOp.from_list([(symmetry.to_label(), 1.0)])
            paulis = qubit_op.primitive.paulis
            len_paulis = len(paulis)
            commuting = len(
                paulis.commutes_with_all(
                    symmetry_op.primitive.paulis)) == len_paulis
            anticommuting = (len(
                paulis.anticommutes_with_all(
                    symmetry_op.primitive.paulis)) == len_paulis)

            if commuting != anticommuting:  # only one of them is True
                if commuting:
                    commutativities.append(True)
                elif anticommuting:
                    commutativities.append(False)
            else:
                raise QiskitNatureError(
                    f"Symmetry {symmetry.to_label()} neither commutes nor anti-commutes "
                    "with excitation operator.")

    return qubit_op, commutativities