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
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