Пример #1
0
    def test_expected_tape(self):
        """Tests if QuantumPhaseEstimation populates the tape as expected for a fixed example"""

        m = qml.RX(0.3, wires=0).matrix

        op = qml.QuantumPhaseEstimation(m,
                                        target_wires=[0],
                                        estimation_wires=[1, 2])
        tape = op.expand()

        with qml.tape.QuantumTape() as tape2:
            qml.Hadamard(1),
            qml.ControlledQubitUnitary(m @ m, control_wires=[1], wires=[0]),
            qml.Hadamard(2),
            qml.ControlledQubitUnitary(m, control_wires=[2], wires=[0]),
            qml.QFT(wires=[1, 2]).inv()

        assert len(tape2.queue) == len(tape.queue)
        assert all([
            op1.name == op2.name for op1, op2 in zip(tape.queue, tape2.queue)
        ])
        assert all([
            op1.wires == op2.wires for op1, op2 in zip(tape.queue, tape2.queue)
        ])
        assert np.allclose(tape.queue[1].matrix, tape2.queue[1].matrix)
        assert np.allclose(tape.queue[3].matrix, tape2.queue[3].matrix)
Пример #2
0
def test_qubit_unitary():
    """Test ctrl on QubitUnitary and ControlledQubitUnitary"""
    with QuantumTape() as tape:
        ctrl(qml.QubitUnitary,
             1)(np.array([[1.0, 1.0], [1.0, -1.0]]) / np.sqrt(2.0), wires=0)

    tape = expand_tape(
        tape, 3, stop_at=lambda op: not isinstance(op, ControlledOperation))
    assert_equal_operations(tape.operations, [
        qml.ControlledQubitUnitary(
            np.array([[1.0, 1.0], [1.0, -1.0]]) / np.sqrt(2.0),
            control_wires=1,
            wires=0)
    ])

    with QuantumTape() as tape:
        ctrl(qml.ControlledQubitUnitary,
             1)(np.array([[1.0, 1.0], [1.0, -1.0]]) / np.sqrt(2.0),
                control_wires=2,
                wires=0)

    tape = expand_tape(
        tape, 3, stop_at=lambda op: not isinstance(op, ControlledOperation))
    assert_equal_operations(tape.operations, [
        qml.ControlledQubitUnitary(
            np.array([[1.0, 1.0], [1.0, -1.0]]) / np.sqrt(2.0),
            control_wires=[1, 2],
            wires=0)
    ])
Пример #3
0
 def test_matrix(self):
     """Test if ControlledQubitUnitary returns the correct matrix for a control-control-X
     (Toffoli) gate"""
     mat = qml.ControlledQubitUnitary(X, control_wires=[0, 1],
                                      wires=2).matrix
     mat2 = qml.Toffoli(wires=[0, 1, 2]).matrix
     assert np.allclose(mat, mat2)
Пример #4
0
    def qfunc(a, b, c, angles):
        qml.RX(a, wires=0)
        qml.RX(b, wires=1)
        qml.PauliZ(1)
        qml.CNOT(wires=[0, 1]).inv()
        qml.CRY(b, wires=[3, 1])
        qml.RX(angles[0], wires=0)
        qml.RX(4 * angles[1], wires=1)
        qml.PhaseShift(17 / 9 * c, wires=2)
        qml.RZ(b, wires=3)
        qml.RX(angles[2], wires=2).inv()
        qml.CRY(0.3589, wires=[3, 1]).inv()
        qml.CSWAP(wires=[4, 2, 1]).inv()
        qml.QubitUnitary(np.eye(2), wires=[2])
        qml.ControlledQubitUnitary(np.eye(2), control_wires=[0, 1], wires=[2])
        qml.MultiControlledX(control_wires=[0, 1, 2], wires=[3])
        qml.Toffoli(wires=[0, 2, 1])
        qml.CNOT(wires=[0, 2])
        qml.PauliZ(wires=[1])
        qml.PauliZ(wires=[1]).inv()
        qml.CZ(wires=[0, 1])
        qml.CZ(wires=[0, 2]).inv()
        qml.CNOT(wires=[2, 1])
        qml.CNOT(wires=[0, 2])
        qml.SWAP(wires=[0, 2]).inv()
        qml.CNOT(wires=[1, 3])
        qml.RZ(b, wires=3)
        qml.CSWAP(wires=[4, 0, 1])

        return [
            qml.expval(qml.PauliY(0)),
            qml.var(qml.Hadamard(wires=1)),
            qml.sample(qml.PauliX(2)),
            qml.expval(qml.Hermitian(np.eye(4), wires=[3, 4])),
        ]
Пример #5
0
    def test_apply(self, n_wires):
        """Test if the apply_controlled_Q performs the correct transformation by reconstructing the
        unitary and comparing against the one provided in make_Q. Random unitaries are chosen for
        a_mat and r_mat."""
        n_all_wires = n_wires + 1

        wires = range(n_wires)
        target_wire = n_wires - 1
        control_wire = n_wires

        a_mat = unitary_group.rvs(2**(n_wires - 1), random_state=1967)
        r_mat = unitary_group.rvs(2**n_wires, random_state=1967)
        q_mat = make_Q(a_mat, r_mat)

        def fn():
            qml.QubitUnitary(a_mat, wires=wires[:-1])
            qml.QubitUnitary(r_mat, wires=wires)

        circ = apply_controlled_Q(fn,
                                  wires=wires,
                                  target_wire=target_wire,
                                  control_wire=control_wire,
                                  work_wires=None)

        u = get_unitary(circ, n_all_wires)

        circ = lambda: qml.ControlledQubitUnitary(
            q_mat, wires=wires, control_wires=control_wire)
        u_ideal = get_unitary(circ, n_all_wires)

        assert np.allclose(u_ideal, u)
Пример #6
0
 def f1():
     qml.QubitUnitary(U1, wires=range(4))
     qml.ControlledQubitUnitary(U,
                                control_wires=control_wires,
                                wires=target_wires)
     qml.QubitUnitary(U2, wires=range(4))
     return qml.state()
Пример #7
0
        def circuit_mixed_polarity():
            qml.templates.ArbitraryStatePreparation(control_state_weights, wires=control_wires)
            qml.templates.ArbitraryStatePreparation(target_state_weights, wires=target_wires)

            qml.ControlledQubitUnitary(
                U, control_wires=control_wires, wires=target_wires, control_values=control_values
            )
            return qml.state()
Пример #8
0
 def test_wrong_shape(self):
     """Test if ControlledQubitUnitary raises a ValueError if a unitary of shape inconsistent
     with wires is provided"""
     with pytest.raises(ValueError,
                        match=r"Input unitary must be of shape \(2, 2\)"):
         qml.ControlledQubitUnitary(np.eye(4),
                                    control_wires=[0, 1],
                                    wires=2)
Пример #9
0
    def test_invalid_mixed_polarity_controls(
        self, control_wires, wires, control_values, expected_error_message
    ):
        """Test if ControlledQubitUnitary properly handles invalid mixed-polarity
        control values."""
        target_wires = Wires(wires)

        with pytest.raises(ValueError, match=expected_error_message):
            qml.ControlledQubitUnitary(
                X, control_wires=control_wires, wires=target_wires, control_values=control_values
            )
Пример #10
0
def op(op_name):
    ops_list = {
        "RX": qml.RX(0.123, wires=0),
        "RY": qml.RY(1.434, wires=0),
        "RZ": qml.RZ(2.774, wires=0),
        "S": qml.S(wires=0),
        "SX": qml.SX(wires=0),
        "T": qml.T(wires=0),
        "CNOT": qml.CNOT(wires=[0, 1]),
        "CZ": qml.CZ(wires=[0, 1]),
        "CY": qml.CY(wires=[0, 1]),
        "SWAP": qml.SWAP(wires=[0, 1]),
        "ISWAP": qml.ISWAP(wires=[0, 1]),
        "SISWAP": qml.SISWAP(wires=[0, 1]),
        "SQISW": qml.SQISW(wires=[0, 1]),
        "CSWAP": qml.CSWAP(wires=[0, 1, 2]),
        "PauliRot": qml.PauliRot(0.123, "Y", wires=0),
        "IsingXX": qml.IsingXX(0.123, wires=[0, 1]),
        "IsingXY": qml.IsingXY(0.123, wires=[0, 1]),
        "IsingYY": qml.IsingYY(0.123, wires=[0, 1]),
        "IsingZZ": qml.IsingZZ(0.123, wires=[0, 1]),
        "Identity": qml.Identity(wires=0),
        "Rot": qml.Rot(0.123, 0.456, 0.789, wires=0),
        "Toffoli": qml.Toffoli(wires=[0, 1, 2]),
        "PhaseShift": qml.PhaseShift(2.133, wires=0),
        "ControlledPhaseShift": qml.ControlledPhaseShift(1.777, wires=[0, 2]),
        "CPhase": qml.CPhase(1.777, wires=[0, 2]),
        "MultiRZ": qml.MultiRZ(0.112, wires=[1, 2, 3]),
        "CRX": qml.CRX(0.836, wires=[2, 3]),
        "CRY": qml.CRY(0.721, wires=[2, 3]),
        "CRZ": qml.CRZ(0.554, wires=[2, 3]),
        "Hadamard": qml.Hadamard(wires=0),
        "PauliX": qml.PauliX(wires=0),
        "PauliY": qml.PauliY(wires=0),
        "PauliZ": qml.PauliZ(wires=0),
        "CRot": qml.CRot(0.123, 0.456, 0.789, wires=[0, 1]),
        "DiagonalQubitUnitary": qml.DiagonalQubitUnitary(np.array([1.0, 1.0j]), wires=1),
        "ControlledQubitUnitary": qml.ControlledQubitUnitary(
            np.eye(2) * 1j, wires=[0], control_wires=[2]
        ),
        "MultiControlledX": qml.MultiControlledX(wires=(0, 1, 2), control_values="01"),
        "SingleExcitation": qml.SingleExcitation(0.123, wires=[0, 3]),
        "SingleExcitationPlus": qml.SingleExcitationPlus(0.123, wires=[0, 3]),
        "SingleExcitationMinus": qml.SingleExcitationMinus(0.123, wires=[0, 3]),
        "DoubleExcitation": qml.DoubleExcitation(0.123, wires=[0, 1, 2, 3]),
        "DoubleExcitationPlus": qml.DoubleExcitationPlus(0.123, wires=[0, 1, 2, 3]),
        "DoubleExcitationMinus": qml.DoubleExcitationMinus(0.123, wires=[0, 1, 2, 3]),
        "QFT": qml.QFT(wires=0),
        "QubitSum": qml.QubitSum(wires=[0, 1, 2]),
        "QubitCarry": qml.QubitCarry(wires=[0, 1, 2, 3]),
        "QubitUnitary": qml.QubitUnitary(np.eye(2) * 1j, wires=0),
    }
    return ops_list.get(op_name)
Пример #11
0
    def test_controlled_qubit_unitary_init(self):
        """Test for the init of ControlledQubitUnitary"""
        control_wires = [3, 2]
        target_wires = [1, 0]
        U = qml.CRX._matrix(0.4)

        op = qml.ControlledQubitUnitary(U, control_wires=control_wires, wires=target_wires)
        target_data = [np.block([[np.eye(12), np.zeros((12, 4))], [np.zeros((4, 12)), U]])]

        assert op.name == qml.ControlledQubitUnitary.__name__
        assert np.allclose(target_data, op.data)
        assert op._wires == Wires(control_wires) + Wires(target_wires)
Пример #12
0
        def circuit_pauli_x():
            qml.templates.ArbitraryStatePreparation(control_state_weights, wires=control_wires)
            qml.templates.ArbitraryStatePreparation(target_state_weights, wires=target_wires)

            for wire in x_locations:
                qml.PauliX(wires=control_wires[wire])

            qml.ControlledQubitUnitary(U, control_wires=control_wires, wires=wires)

            for wire in x_locations:
                qml.PauliX(wires=control_wires[wire])

            return qml.state()
Пример #13
0
    def expand(self):
        unitary = self.parameters[0]
        unitary_powers = [unitary]

        for _ in range(len(self.estimation_wires) - 1):
            new_power = unitary_powers[-1] @ unitary_powers[-1]
            unitary_powers.append(new_power)

        with qml.tape.QuantumTape() as tape:
            for wire in self.estimation_wires:
                qml.Hadamard(wire)
                qml.ControlledQubitUnitary(unitary_powers.pop(),
                                           control_wires=wire,
                                           wires=self.target_wires)

            qml.QFT(wires=self.estimation_wires).inv()

        return tape
Пример #14
0
def parameterized_qubit_tape():
    """A parametrized qubit ciruit."""
    a, b, c = 0.1, 0.2, 0.3
    angles = np.array([0.4, 0.5, 0.6])

    with qml.tape.QuantumTape() as tape:
        qml.RX(a, wires=0)
        qml.RX(b, wires=1)
        qml.PauliZ(1)
        qml.CNOT(wires=[0, 1]).inv()
        qml.CRY(b, wires=[3, 1])
        qml.RX(angles[0], wires=0)
        qml.RX(4 * angles[1], wires=1)
        qml.PhaseShift(17 / 9 * c, wires=2)
        qml.RZ(b, wires=3)
        qml.RX(angles[2], wires=2).inv()
        qml.CRY(0.3589, wires=[3, 1]).inv()
        qml.CSWAP(wires=[4, 2, 1]).inv()
        qml.QubitUnitary(np.eye(2), wires=[2])
        qml.ControlledQubitUnitary(np.eye(2), control_wires=[0, 1], wires=[2])
        qml.MultiControlledX(control_wires=[0, 1, 2], wires=[3])
        qml.Toffoli(wires=[0, 2, 1])
        qml.CNOT(wires=[0, 2])
        qml.PauliZ(wires=[1])
        qml.PauliZ(wires=[1]).inv()
        qml.CZ(wires=[0, 1])
        qml.CZ(wires=[0, 2]).inv()
        qml.CY(wires=[1, 2])
        qml.CY(wires=[2, 0]).inv()
        qml.CNOT(wires=[2, 1])
        qml.CNOT(wires=[0, 2])
        qml.SWAP(wires=[0, 2]).inv()
        qml.CNOT(wires=[1, 3])
        qml.RZ(b, wires=3)
        qml.CSWAP(wires=[4, 0, 1])

        qml.expval(qml.PauliY(0)),
        qml.var(qml.Hadamard(wires=1)),
        qml.sample(qml.PauliX(2)),
        qml.expval(qml.Hermitian(np.eye(4), wires=[3, 4])),

    return tape
Пример #15
0
def _get_gen_op(op, allow_nonunitary, aux_wire):
    r"""Get the controlled-generator operation for a given operation.

    Args:
        op (pennylane.operation.Operation): Operation from which to extract the generator
        allow_nonunitary (bool): Whether non-unitary gates are allowed in the circuit
        aux_wire (int or pennylane.wires.Wires): Auxiliary wire on which to control the operation

    Returns
        qml.Operation: Controlled-generator operation of the generator of ``op``, controlled
        on wire ``aux_wire``.

    Raises
        ValueError: If the generator of ``op`` is not known or it is non-unitary while
        ``allow_nonunitary=False``.

    If ``allow_nonunitary=True``, a general :class:`~.pennylane.ControlledQubitUnitary` is returned,
    otherwise only controlled Pauli operations are used. If the operation has a non-unitary
    generator but ``allow_nonunitary=False``, the operation ``op`` should have been decomposed
    before, leading to a ``ValueError``.
    """
    gen, _ = op.generator
    try:
        if isinstance(gen, np.ndarray):
            cgen = _OP_TO_CGEN[op.__class__]
        else:
            cgen = _GEN_TO_CGEN.get(gen, None)
            if cgen is None:
                cgen = _OP_TO_CGEN[op.__class__]
        return cgen(wires=[aux_wire, *op.wires])

    except KeyError as e:
        if allow_nonunitary:
            if (not isinstance(gen, np.ndarray)) and issubclass(
                    gen, qml.operation.Observable):
                gen = gen.matrix
            return qml.ControlledQubitUnitary(gen,
                                              control_wires=aux_wire,
                                              wires=op.wires)
        raise ValueError(
            f"Generator for operation {op} not known and non-unitary operations "
            "deactivated via allow_nonunitary=False.") from e
Пример #16
0
def test_apply_controlled_v(n_wires):
    """Test if the _apply_controlled_v performs the correct transformation by reconstructing the
    unitary and comparing against the one provided in _make_V."""
    n_all_wires = n_wires + 1

    wires = Wires(range(n_wires))
    control_wire = Wires(n_wires)

    circ = lambda: _apply_controlled_v(target_wire=Wires([n_wires - 1]),
                                       control_wire=control_wire)
    u = get_unitary(circ, n_all_wires)

    # Note the sign flip in the following. The sign does not matter when performing the Q unitary
    # because two Vs are used.
    v_ideal = -_make_V(2**n_wires)

    circ = lambda: qml.ControlledQubitUnitary(
        v_ideal, wires=wires, control_wires=control_wire)
    u_ideal = get_unitary(circ, n_all_wires)

    assert np.allclose(u, u_ideal)
Пример #17
0
def expand_with_control(tape, control_wire):
    """Expand a tape to include a control wire on all queued operations.

    Args:
        tape (.QuantumTape): quantum tape to be controlled
        control_wire (int): a single wire to use as the control wire

    Returns:
        .QuantumTape: A new QuantumTape with the controlled operations.
    """
    with QuantumTape(do_queue=False) as new_tape:
        for op in tape.operations:
            if hasattr(op, "_controlled"):
                # Execute the controlled version of the operation
                # and add that the to the tape context.
                # pylint: disable=protected-access
                op._controlled(control_wire)
            else:
                # Attempt to decompose the operation and apply
                # controls to each gate in the decomposition.
                with new_tape.stop_recording():
                    try:
                        tmp_tape = op.expand()

                    except NotImplementedError:
                        # No decomposition is defined. Create a
                        # ControlledQubitUnitary gate using the operation
                        # matrix representation.
                        with QuantumTape() as tmp_tape:
                            qml.ControlledQubitUnitary(
                                op.matrix,
                                control_wires=control_wire,
                                wires=op.wires)

                tmp_tape = expand_with_control(tmp_tape, control_wire)
                requeue_ops_in_tape(tmp_tape)

    return new_tape
Пример #18
0
 "CRZ": qml.CRZ(0, wires=[0, 1]),
 "CRot": qml.CRot(0, 0, 0, wires=[0, 1]),
 "CSWAP": qml.CSWAP(wires=[0, 1, 2]),
 "CZ": qml.CZ(wires=[0, 1]),
 "CY": qml.CY(wires=[0, 1]),
 "DiagonalQubitUnitary": qml.DiagonalQubitUnitary(np.array([1, 1]), wires=[0]),
 "Hadamard": qml.Hadamard(wires=[0]),
 "MultiRZ": qml.MultiRZ(0, wires=[0]),
 "PauliX": qml.PauliX(wires=[0]),
 "PauliY": qml.PauliY(wires=[0]),
 "PauliZ": qml.PauliZ(wires=[0]),
 "PhaseShift": qml.PhaseShift(0, wires=[0]),
 "ControlledPhaseShift": qml.ControlledPhaseShift(0, wires=[0, 1]),
 "QubitStateVector": qml.QubitStateVector(np.array([1.0, 0.0]), wires=[0]),
 "QubitUnitary": qml.QubitUnitary(np.eye(2), wires=[0]),
 "ControlledQubitUnitary": qml.ControlledQubitUnitary(np.eye(2), control_wires=[1], wires=[0]),
 "MultiControlledX": qml.MultiControlledX(control_wires=[1, 2], wires=[0]),
 "RX": qml.RX(0, wires=[0]),
 "RY": qml.RY(0, wires=[0]),
 "RZ": qml.RZ(0, wires=[0]),
 "Rot": qml.Rot(0, 0, 0, wires=[0]),
 "S": qml.S(wires=[0]),
 "SWAP": qml.SWAP(wires=[0, 1]),
 "T": qml.T(wires=[0]),
 "SX": qml.SX(wires=[0]),
 "Toffoli": qml.Toffoli(wires=[0, 1, 2]),
 "QFT": qml.QFT(wires=[0, 1, 2]),
 "SingleExcitation": qml.SingleExcitation(0, wires=[0, 1]),
 "SingleExcitationPlus": qml.SingleExcitationPlus(0, wires=[0, 1]),
 "SingleExcitationMinus": qml.SingleExcitationMinus(0, wires=[0, 1]),
 "DoubleExcitation": qml.DoubleExcitation(0, wires=[0, 1, 2, 3]),
Пример #19
0
 def test_shared_control(self):
     """Test if ControlledQubitUnitary raises an error if control wires are shared with wires"""
     with pytest.raises(
             ValueError,
             match="The control wires must be different from the wires"):
         qml.ControlledQubitUnitary(X, control_wires=[0, 2], wires=2)
Пример #20
0
 def test_no_control(self):
     """Test if ControlledQubitUnitary raises an error if control wires are not specified"""
     with pytest.raises(ValueError, match="Must specify control wires"):
         qml.ControlledQubitUnitary(X, wires=2)
Пример #21
0
                qml.PauliX(wires=control_wires[wire])

            qml.ControlledQubitUnitary(U,
                                       control_wires=control_wires,
                                       wires=wires)

            for wire in x_locations:
                qml.PauliX(wires=control_wires[wire])

            return qml.state()

        mixed_polarity_state = circuit_mixed_polarity()
        pauli_x_state = circuit_pauli_x()

        assert np.allclose(mixed_polarity_state, pauli_x_state)


label_data = [
    (qml.QubitUnitary(X, wires=0), "U"),
    (qml.DiagonalQubitUnitary([1, 1], wires=1), "U"),
    (qml.ControlledQubitUnitary(X, control_wires=0, wires=1), "U"),
]


@pytest.mark.parametrize("op, label", label_data)
def test_label(op, label):
    assert op.label() == label
    assert op.label(decimals=5) == label
    op.inv()
    assert op.label() == label + "⁻¹"
Пример #22
0
def QuantumPhaseEstimation(unitary, target_wires, estimation_wires):
    r"""Performs the
    `quantum phase estimation <https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm>`__
    circuit.

    Given a unitary matrix :math:`U`, this template applies the circuit for quantum phase
    estimation. The unitary is applied to the qubits specified by ``target_wires`` and :math:`n`
    qubits are used for phase estimation as specified by ``estimation_wires``.

    .. figure:: ../../_static/templates/subroutines/qpe.svg
        :align: center
        :width: 60%
        :target: javascript:void(0);

    This circuit can be used to perform the standard quantum phase estimation algorithm, consisting
    of the following steps:

    #. Prepare ``target_wires`` in a given state. If ``target_wires`` are prepared in an eigenstate
       of :math:`U` that has corresponding eigenvalue :math:`e^{2 \pi i \theta}` with phase
       :math:`\theta \in [0, 1)`, this algorithm will measure :math:`\theta`. Other input states can
       be prepared more generally.
    #. Apply the ``QuantumPhaseEstimation`` circuit.
    #. Measure ``estimation_wires`` using :func:`~.probs`, giving a probability distribution over
       measurement outcomes in the computational basis.
    #. Find the index of the largest value in the probability distribution and divide that number by
       :math:`2^{n}`. This number will be an estimate of :math:`\theta` with an error that decreases
       exponentially with the number of qubits :math:`n`.

    Note that if :math:`\theta \in (-1, 0]`, we can estimate the phase by again finding the index
    :math:`i` found in step 4 and calculating :math:`\theta \approx \frac{1 - i}{2^{n}}`. The
    usage details below give an example of this case.

    Args:
        unitary (array): the phase estimation unitary, specified as a matrix
        target_wires (Union[Wires, Sequence[int], or int]): the target wires to apply the unitary
        estimation_wires (Union[Wires, Sequence[int], or int]): the wires to be used for phase
            estimation

    Raises:
        QuantumFunctionError: if the ``target_wires`` and ``estimation_wires`` share a common
            element

    .. UsageDetails::

        Consider the matrix corresponding to a rotation from an :class:`~.RX` gate:

        .. code-block:: python

            import pennylane as qml
            from pennylane.templates import QuantumPhaseEstimation
            from pennylane import numpy as np

            phase = 5
            target_wires = [0]
            unitary = qml.RX(phase, wires=0).matrix

        The ``phase`` parameter can be estimated using ``QuantumPhaseEstimation``. An example is
        shown below using a register of five phase-estimation qubits:

        .. code-block:: python

            n_estimation_wires = 5
            estimation_wires = range(1, n_estimation_wires + 1)

            dev = qml.device("default.qubit", wires=n_estimation_wires + 1)

            @qml.qnode(dev)
            def circuit():
                # Start in the |+> eigenstate of the unitary
                qml.Hadamard(wires=target_wires)

                QuantumPhaseEstimation(
                    unitary,
                    target_wires=target_wires,
                    estimation_wires=estimation_wires,
                )

                return qml.probs(estimation_wires)

            phase_estimated = np.argmax(circuit()) / 2 ** n_estimation_wires

            # Need to rescale phase due to convention of RX gate
            phase_estimated = 4 * np.pi * (1 - phase_estimated)
    """

    target_wires = Wires(target_wires)
    estimation_wires = Wires(estimation_wires)

    if len(Wires.shared_wires([target_wires, estimation_wires])) != 0:
        raise qml.QuantumFunctionError(
            "The target wires and estimation wires must be different")

    unitary_powers = [unitary]

    for _ in range(len(estimation_wires) - 1):
        new_power = unitary_powers[-1] @ unitary_powers[-1]
        unitary_powers.append(new_power)

    for wire in estimation_wires:
        qml.Hadamard(wire)
        qml.ControlledQubitUnitary(unitary_powers.pop(),
                                   control_wires=wire,
                                   wires=target_wires)

    qml.QFT(wires=estimation_wires).inv()
 def qfunc():
     qml.PauliX(wires=2)
     qml.ControlledQubitUnitary(np.array([[0, 1], [1, 0]]),
                                control_wires=0,
                                wires=2)
     qml.PauliX(wires=2)