def test_QFT(self, inverse): """Test if the QFT matrix is equal to a manually-calculated version for 3 qubits""" op = qml.QFT(wires=range(3)).inv() if inverse else qml.QFT( wires=range(3)) res = op.matrix exp = QFT.conj().T if inverse else QFT assert np.allclose(res, exp)
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)
def circuit(x, z): qml.QFT(wires=(0, 1, 2, 3)) qml.Toffoli(wires=(0, 1, 2)) qml.CSWAP(wires=(0, 2, 3)) qml.RX(x, wires=0) qml.CRZ(z, wires=(3, 0)) return qml.expval(qml.PauliZ(0))
def test_QFT_adjoint_decomposition(self, n_qubits): # tol """Test if the QFT adjoint operation has the right decomposition""" # QFT adjoint has right decompositions qft = qml.QFT(wires=range(n_qubits)) qft_dec = qft.expand().operations expected_op = [x.adjoint() for x in qft_dec] expected_op.reverse() adj = qml.QFT(wires=range(n_qubits)).adjoint() op = adj.expand().operations for j in range(0, len(op)): assert op[j].name == expected_op[j].name assert op[j].wires == expected_op[j].wires assert op[j].parameters == expected_op[j].parameters
def test_notches(self, wires, n): """Test notches are included when non-active wires exist.""" with QuantumTape() as tape: qml.QFT(wires=wires) _, ax = tape_mpl(tape, show_all_wires=True, wire_order=[0, 1, 2]) assert len(ax.patches) == (n + 1) plt.close()
def test_QFT_decomposition(self, n_qubits): """Test if the QFT operation is correctly decomposed""" op = qml.QFT(wires=range(n_qubits)) decomp = op.decompose() dev = qml.device("default.qubit", wires=n_qubits) out_states = [] for state in np.eye(2**n_qubits): dev.reset() ops = [qml.QubitStateVector(state, wires=range(n_qubits))] + decomp dev.apply(ops) out_states.append(dev.state) reconstructed_unitary = np.array(out_states).T expected_unitary = qml.QFT(wires=range(n_qubits)).matrix assert np.allclose(reconstructed_unitary, expected_unitary)
def qfunc_adder(m, wires): """Quantum function capable of adding m units to a basic state given as input. Args: - m (int): units to add. - wires (list(int)): list of wires in which the function will be executed on. """ qml.QFT(wires=wires) # QHACK # nwires = len(wires) for i in range(nwires): qml.RZ(2**i / 2**nwires * 2 * np.pi * m, wires=(nwires - i - 1)) # QHACK # qml.QFT(wires=wires).inv()
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)
def test_active_wire_notches_False(self): """Test active wire notches are disable with active_wire_notches=False.""" with QuantumTape() as tape: qml.QFT(wires=(0, 3)) _, ax = tape_mpl(tape, show_all_wires=True, wire_order=[0, 1, 2, 3], active_wire_notches=False) assert len(ax.patches) == 1
def test_QFT_adjoint_method(self, num_inversions): """Test the adjoint method of the QFT class""" op = qml.QFT(wires=range(3)) for _ in range(num_inversions): op = op.adjoint() res = op.matrix inverse = num_inversions % 2 == 1 exp = QFT.conj().T if inverse else QFT assert np.allclose(res, exp) assert op.inverse is inverse
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
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 temp_circ(): qml.QFT(wires=(0, 1.23)) return qml.probs(0)
def qfunc1(): qml.RX(2, wires=0) qml.RY(-3, wires=1) qml.QFT(wires=[0, 1, 2]) qml.SWAP(wires=[1, 2]) return qml.state()
def circ(n_qubits): qml.adjoint(qml.QFT)(wires=range(n_qubits)) qml.QFT(wires=range(n_qubits)) return qml.state()
def qfunc2(): qml.RX(2, wires=0) qml.RY(-3, wires=2) qml.QFT(wires=[0, 2, 1]) return qml.state()
# two wire labels, so CRX is third text object assert ax.texts[2].get_text() == "RX\n(1.23)" plt.close() general_op_data = [ qml.RX(1.234, wires=0), qml.Hadamard(0), qml.S(wires=0), qml.IsingXX(1.234, wires=(0, 1)), qml.U3(1.234, 2.345, 3.456, wires=0), # State Prep qml.BasisState([0, 1, 0], wires=(0, 1, 2)), ### Templates qml.QFT(wires=range(3)), qml.Permute([4, 2, 0, 1, 3], wires=(0, 1, 2, 3, 4)), qml.GroverOperator(wires=(0, 1, 2, 3, 4, 5)), ### Continuous Variable qml.Kerr(1.234, wires=0), qml.Beamsplitter(1.234, 2.345, wires=(0, 1)), qml.Rotation(1.234, wires=0), ] class TestGeneralOperations: """Tests general operations.""" width = 0.75 - 2 * 0.2 @pytest.mark.parametrize("op", general_op_data)
"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]), "DoubleExcitationPlus": qml.DoubleExcitationPlus(0, wires=[0, 1, 2, 3]), "DoubleExcitationMinus": qml.DoubleExcitationMinus(0, wires=[0, 1, 2, 3]), "QubitCarry": qml.QubitCarry(wires=[0, 1, 2, 3]), "QubitSum:": qml.QubitSum(wires=[0, 1, 2]), } all_ops = ops.keys() # non-parametrized qubit gates I = np.identity(2) X = np.array([[0, 1], [1, 0]])
fig.suptitle("My Circuit", fontsize="xx-large") options = {'facecolor': "white", 'edgecolor': "#f57e7e", "linewidth": 6, "zorder": -1} box1 = plt.Rectangle((-0.5, -0.5), width=3.0, height=4.0, **options) ax.add_patch(box1) ax.annotate("CSWAP", xy=(3, 2.5), xycoords='data', xytext=(3.8,1.5), textcoords='data', arrowprops={'facecolor': 'black'}, fontsize=14) plt.savefig(folder / "postprocessing.png") plt.close() if __name__ == "__main__": with qml.tape.QuantumTape() as tape: qml.QFT(wires=(0,1,2,3)) qml.IsingXX(1.234, wires=(0,2)) qml.Toffoli(wires=(0,1,2)) qml.CSWAP(wires=(0,2,3)) qml.RX(1.2345, wires=0) qml.CRZ(1.2345, wires=(3,0)) qml.expval(qml.PauliZ(0)) default(tape) decimals() wire_order(tape) show_all_wires(tape) use_style(tape) rcparams(tape) wires_and_labels(tape) postprocessing(tape)