示例#1
0
def apply_controlled_Q(fn, wires, target_wire, control_wire, work_wires):
    r"""Provides the circuit to apply a controlled version of the :math:`\mathcal{Q}` unitary
    defined in `this <https://arxiv.org/abs/1805.00109>`__ paper.

    The input ``fn`` should be the quantum circuit corresponding to the :math:`\mathcal{F}` unitary
    in the paper above. This function transforms this circuit into a controlled version of the
    :math:`\mathcal{Q}` unitary, which forms part of the quantum Monte Carlo algorithm. The
    :math:`\mathcal{Q}` unitary encodes the target expectation value as a phase in one of its
    eigenvalues. This phase can be estimated using quantum phase estimation (see
    :class:`~.QuantumPhaseEstimation` for more details).

    Args:
        fn (Callable): a quantum function that applies quantum operations according to the
            :math:`\mathcal{F}` unitary used as part of quantum Monte Carlo estimation
        wires (Union[Wires or Sequence[int]]): the wires acted upon by the ``fn`` circuit
        target_wire (Union[Wires, int]): The wire in which the expectation value is encoded. Must be
            contained within ``wires``.
        control_wire (Union[Wires, int]): the control wire from the register of phase estimation
            qubits
        work_wires (Union[Wires, Sequence[int], or int]): additional work wires used when
            decomposing :math:`\mathcal{Q}`

    Returns:
        function: The input function transformed to the :math:`\mathcal{Q}` unitary

    Raises:
        ValueError: if ``target_wire`` is not in ``wires``
    """
    fn_inv = adjoint(fn)

    wires = Wires(wires)
    target_wire = Wires(target_wire)
    control_wire = Wires(control_wire)
    work_wires = Wires(work_wires)

    if not wires.contains_wires(target_wire):
        raise ValueError("The target wire must be contained within wires")

    @wraps(fn)
    def wrapper(*args, **kwargs):
        _apply_controlled_v(target_wire=target_wire, control_wire=control_wire)
        fn_inv(*args, **kwargs)
        _apply_controlled_z(wires=wires,
                            control_wire=control_wire,
                            work_wires=work_wires)
        fn(*args, **kwargs)

        _apply_controlled_v(target_wire=target_wire, control_wire=control_wire)
        fn_inv(*args, **kwargs)
        _apply_controlled_z(wires=wires,
                            control_wire=control_wire,
                            work_wires=work_wires)
        fn(*args, **kwargs)

    return wrapper
示例#2
0
    def test_contains_wires(self, ):
        """Tests the dedicated contains_wires() method."""

        wires = Wires([0, 1, 2, 3, Wires([4, 5]), None])

        assert wires.contains_wires(Wires([0, 3]))
        assert wires.contains_wires(Wires([1, 2, None]))
        assert wires.contains_wires(Wires([Wires(
            [4, 5])]))  # Wires([4, 5]) is just a label!

        assert not wires.contains_wires(0)  # wrong type
        assert not wires.contains_wires([0, 1])  # wrong type
        assert not wires.contains_wires(Wires(
            [4, 5]))  # looks up 4 and 5 in wires, which are not present