Пример #1
0
 def circuit():
     """A combination of two and three qubit gates with the one_qubit_block and a simple
     PauliZ measurement applied to an input basis state"""
     qml.BasisState(np.array(basis_state), wires=[0, 1, 2])
     qml.RX(0.5, wires=0)
     qml.Hadamard(wires=1)
     qml.RY(0.9, wires=2)
     qml.CNOT(wires=[0, 1])
     qml.CNOT(wires=[2, 0])
     qml.CZ(wires=[1, 0])
     one_qubit_block(wires=0)
     qml.Toffoli(wires=[1, 0, 2])
     one_qubit_block(wires=2)
     qml.SWAP(wires=[0, 1])
     qml.SWAP(wires=[0, 2])
     qml.CRX(0.5, wires=[1, 0])
     qml.CSWAP(wires=[2, 1, 0])
     qml.CRY(0.9, wires=[2, 1])
     one_qubit_block(wires=1)
     qml.CRZ(0.02, wires=[0, 1])
     qml.CRot(0.2, 0.3, 0.7, wires=[2, 1])
     qml.RZ(0.4, wires=0)
     qml.Toffoli(wires=[2, 1, 0])
     return qml.expval(qml.PauliZ(0))
class TestDrawableLayers:
    """Tests for `drawable_layers`"""
    def test_single_wires_no_blocking(self):
        """Test simple case where nothing blocks each other"""

        ops = [qml.PauliX(0), qml.PauliX(1), qml.PauliX(2)]

        layers = drawable_layers(ops)

        assert layers == [set(ops)]

    def test_single_wires_blocking(self):
        """Test single wire gates blocking each other"""

        ops = [qml.PauliX(0), qml.PauliX(0), qml.PauliX(0)]

        layers = drawable_layers(ops)

        assert layers == [{ops[0]}, {ops[1]}, {ops[2]}]

    @pytest.mark.parametrize(
        "multiwire_gate",
        (
            qml.CNOT(wires=(0, 2)),
            qml.CNOT(wires=(2, 0)),
            qml.Toffoli(wires=(0, 2, 3)),
            qml.Toffoli(wires=(2, 3, 0)),
            qml.Toffoli(wires=(3, 0, 2)),
            qml.Toffoli(wires=(0, 3, 2)),
            qml.Toffoli(wires=(3, 2, 0)),
            qml.Toffoli(wires=(2, 0, 3)),
        ),
    )
    def test_multiwire_blocking(self, multiwire_gate):
        """Test multi-wire gate blocks on unused wire"""

        wire_map = {0: 0, 1: 1, 2: 2, 3: 3}
        ops = [qml.PauliZ(1), multiwire_gate, qml.PauliX(1)]

        layers = drawable_layers(ops, wire_map=wire_map)

        assert layers == [{ops[0]}, {ops[1]}, {ops[2]}]

    @pytest.mark.parametrize("measurement", (qml.state(), qml.sample()))
    def test_all_wires_measurement(self, measurement):
        """Test measurements that act on all wires also block on all available wires."""

        ops = [qml.PauliX(0), measurement, qml.PauliY(1)]

        layers = drawable_layers(ops)

        assert layers == [{ops[0]}, {ops[1]}, {ops[2]}]
Пример #3
0
    def test_four_qubit_random_circuit(self, shots):
        """Test a four-qubit random circuit with the whole set of possible gates,
        the test is analog to a failing device test and is used to check the try/except
        expval function from the mixed_simulator device."""
        dev = qml.device("cirq.mixedsimulator", wires=4)

        gates = [
            qml.PauliX(wires=0),
            qml.PauliY(wires=1),
            qml.PauliZ(wires=2),
            qml.S(wires=3),
            qml.T(wires=0),
            qml.RX(2.3, wires=1),
            qml.RY(1.3, wires=2),
            qml.RZ(3.3, wires=3),
            qml.Hadamard(wires=0),
            qml.Rot(0.1, 0.2, 0.3, wires=1),
            qml.CRot(0.1, 0.2, 0.3, wires=[2, 3]),
            qml.Toffoli(wires=[0, 1, 2]),
            qml.SWAP(wires=[1, 2]),
            qml.CSWAP(wires=[1, 2, 3]),
            qml.U1(1.0, wires=0),
            qml.U2(1.0, 2.0, wires=2),
            qml.U3(1.0, 2.0, 3.0, wires=3),
            qml.CRX(0.1, wires=[1, 2]),
            qml.CRY(0.2, wires=[2, 3]),
            qml.CRZ(0.3, wires=[3, 1]),
        ]

        layers = 3
        np.random.seed(1967)
        gates_per_layers = [pnp.random.permutation(gates).numpy() for _ in range(layers)]

        def circuit():
            """4-qubit circuit with layers of randomly selected gates and random connections for
            multi-qubit gates."""
            np.random.seed(1967)
            for gates in gates_per_layers:
                for gate in gates:
                    qml.apply(gate)
            return qml.expval(qml.PauliZ(0))

        qnode = qml.QNode(circuit, dev)
        assert np.allclose(qnode(), 0.0)
Пример #4
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
Пример #5
0
    def test_Toffoli(self):
        """Test Toffoli gets a special call."""

        with QuantumTape() as tape:
            qml.Toffoli(wires=(0, 1, 2))

        _, ax = tape_mpl(tape)
        layer = 0

        assert len(ax.patches) == 3
        assert ax.patches[0].center == (layer, 0)
        assert ax.patches[1].center == (layer, 1)
        assert ax.patches[2].center == (layer, 2)

        # three wires, one control line, two target lines
        assert len(ax.lines) == 6
        control_line = ax.lines[3]
        assert control_line.get_data() == ((layer, layer), (0, 2))

        plt.close()
Пример #6
0
    def circuit(self, a, b):
        aBasis = i_to_basis(a, pad=self.reg_a_size)
        bBasis = i_to_basis(b, pad=self.reg_a_size)
        zeros = [0] * (self.reg_b_size - self.reg_a_size)
        ancilla = [0] * (self.ancilla_size)
        qml.BasisState(np.array(aBasis + zeros + bBasis + ancilla),
                       wires=range(self.reg_a_size + self.reg_b_size +
                                   self.ancilla_size))

        for g in self.gateSet:
            if len(g) == 1:
                qml.PauliX(g[0])
            if len(g) == 2:
                qml.CNOT(wires=list(g))
            if len(g) == 3:
                qml.Toffoli(wires=list(g))

        return [
            qml.expval(qml.PauliZ(i))
            for i in range(self.reg_a_size + self.reg_b_size)
        ]
Пример #7
0
    def test_unitary_to_rot_too_big_unitary(self):
        """Test that the transform ignores QubitUnitary instances that are too big
        to decompose."""

        tof = qml.Toffoli(wires=[0, 1, 2]).matrix

        def qfunc():
            qml.QubitUnitary(H, wires="a")
            qml.QubitUnitary(tof, wires=["a", "b", "c"])

        transformed_qfunc = unitary_to_rot(qfunc)

        ops = qml.transforms.make_tape(transformed_qfunc)().operations

        assert len(ops) == 2

        assert ops[0].name == "Rot"
        assert ops[0].wires == Wires("a")

        assert ops[1].name == "QubitUnitary"
        assert ops[1].wires == Wires(["a", "b", "c"])
Пример #8
0
def test_ctrl_within_ctrl():
    """Test using ctrl on a method that uses ctrl."""
    def ansatz(params):
        qml.RX(params[0], wires=0)
        ctrl(qml.PauliX, control=0)(wires=1)
        qml.RX(params[1], wires=0)

    controlled_ansatz = ctrl(ansatz, 2)

    with QuantumTape() as tape:
        controlled_ansatz([0.123, 0.456])

    tape = expand_tape(
        tape, 2, stop_at=lambda op: not isinstance(op, ControlledOperation))

    expected = [
        qml.CRX(0.123, wires=[2, 0]),
        qml.Toffoli(wires=[0, 2, 1]),
        qml.CRX(0.456, wires=[2, 0])
    ]
    assert_equal_operations(tape.operations, expected)
Пример #9
0
def test_integration():
    gates = [
        qml.PauliX(wires=0),
        qml.PauliY(wires=0),
        qml.PauliZ(wires=0),
        qml.S(wires=0),
        qml.T(wires=0),
        qml.RX(0.4, wires=0),
        qml.RY(0.4, wires=0),
        qml.RZ(0.4, wires=0),
        qml.Hadamard(wires=0),
        qml.Rot(0.4, 0.5, 0.6, wires=1),
        qml.CRot(0.4, 0.5, 0.6, wires=(0, 1)),
        qml.Toffoli(wires=(0, 1, 2)),
        qml.SWAP(wires=(0, 1)),
        qml.CSWAP(wires=(0, 1, 2)),
        qml.U1(0.4, wires=0),
        qml.U2(0.4, 0.5, wires=0),
        qml.U3(0.4, 0.5, 0.6, wires=0),
        qml.CRX(0.4, wires=(0, 1)),
        qml.CRY(0.4, wires=(0, 1)),
        qml.CRZ(0.4, wires=(0, 1)),
    ]

    layers = 3
    np.random.seed(1967)
    gates_per_layers = [np.random.permutation(gates) for _ in range(layers)]

    with qml.tape.QuantumTape() as tape:
        np.random.seed(1967)
        for gates in gates_per_layers:
            for gate in gates:
                qml.apply(gate)

    base_circ = from_pennylane(tape)
    tape_recovered = to_pennylane(base_circ)
    circ_recovered = from_pennylane(tape_recovered)
    u_1 = cirq.unitary(base_circ)
    u_2 = cirq.unitary(circ_recovered)
    cirq.testing.assert_allclose_up_to_global_phase(u_1, u_2, atol=0)
Пример #10
0
    def test_toffoli_decomposition(self, tol):
        """Tests that the decomposition of the Toffoli gate is correct"""
        op = qml.Toffoli(wires=[0, 1, 2])
        res = op.decompose()

        assert len(res) == 15

        mats = []

        for i in reversed(res):
            if i.wires == Wires([2]):
                mats.append(np.kron(np.eye(4), i.matrix))
            elif i.wires == Wires([1]):
                mats.append(np.kron(np.eye(2), np.kron(i.matrix, np.eye(2))))
            elif i.wires == Wires([0]):
                mats.append(np.kron(i.matrix, np.eye(4)))
            elif i.wires == Wires([0, 1]) and i.name == "CNOT":
                mats.append(np.kron(i.matrix, np.eye(2)))
            elif i.wires == Wires([1, 2]) and i.name == "CNOT":
                mats.append(np.kron(np.eye(2), i.matrix))
            elif i.wires == Wires([0, 2]) and i.name == "CNOT":
                mats.append(
                    np.array(
                        [
                            [1, 0, 0, 0, 0, 0, 0, 0],
                            [0, 1, 0, 0, 0, 0, 0, 0],
                            [0, 0, 1, 0, 0, 0, 0, 0],
                            [0, 0, 0, 1, 0, 0, 0, 0],
                            [0, 0, 0, 0, 0, 1, 0, 0],
                            [0, 0, 0, 0, 1, 0, 0, 0],
                            [0, 0, 0, 0, 0, 0, 0, 1],
                            [0, 0, 0, 0, 0, 0, 1, 0],
                        ]
                    )
                )

        decomposed_matrix = np.linalg.multi_dot(mats)

        assert np.allclose(decomposed_matrix, op.matrix, atol=tol, rtol=0)
Пример #11
0
    def decomposition(self, *args, **kwargs):

        if len(self.control_wires) > 2 and len(self._work_wires) == 0:
            raise ValueError(
                f"At least one work wire is required to decompose operation: {self}"
            )

        flips1 = [
            qml.PauliX(self.control_wires[i])
            for i, val in enumerate(self.control_values) if val == "0"
        ]

        if len(self.control_wires) == 1:
            decomp = [
                qml.CNOT(wires=[self.control_wires[0], self._target_wire])
            ]
        elif len(self.control_wires) == 2:
            decomp = [
                qml.Toffoli(wires=[*self.control_wires, self._target_wire])
            ]
        else:
            num_work_wires_needed = len(self.control_wires) - 2

            if len(self._work_wires) >= num_work_wires_needed:
                decomp = self._decomposition_with_many_workers(
                    self.control_wires, self._target_wire, self._work_wires)
            else:
                work_wire = self._work_wires[0]
                decomp = self._decomposition_with_one_worker(
                    self.control_wires, self._target_wire, work_wire)

        flips2 = [
            qml.PauliX(self.control_wires[i])
            for i, val in enumerate(self.control_values) if val == "0"
        ]

        return flips1 + decomp + flips2
Пример #12
0
    def _decomposition_with_many_workers(control_wires, target_wire,
                                         work_wires):
        """Decomposes the multi-controlled PauliX gate using the approach in Lemma 7.2 of
        https://arxiv.org/pdf/quant-ph/9503016.pdf, which requires a suitably large register of
        work wires"""
        num_work_wires_needed = len(control_wires) - 2
        work_wires = work_wires[:num_work_wires_needed]

        work_wires_reversed = list(reversed(work_wires))
        control_wires_reversed = list(reversed(control_wires))

        gates = []

        for i in range(len(work_wires)):
            ctrl1 = control_wires_reversed[i]
            ctrl2 = work_wires_reversed[i]
            t = target_wire if i == 0 else work_wires_reversed[i - 1]
            gates.append(qml.Toffoli(wires=[ctrl1, ctrl2, t]))

        gates.append(qml.Toffoli(wires=[*control_wires[:2], work_wires[0]]))

        for i in reversed(range(len(work_wires))):
            ctrl1 = control_wires_reversed[i]
            ctrl2 = work_wires_reversed[i]
            t = target_wire if i == 0 else work_wires_reversed[i - 1]
            gates.append(qml.Toffoli(wires=[ctrl1, ctrl2, t]))

        for i in range(len(work_wires) - 1):
            ctrl1 = control_wires_reversed[i + 1]
            ctrl2 = work_wires_reversed[i + 1]
            t = work_wires_reversed[i]
            gates.append(qml.Toffoli(wires=[ctrl1, ctrl2, t]))

        gates.append(qml.Toffoli(wires=[*control_wires[:2], work_wires[0]]))

        for i in reversed(range(len(work_wires) - 1)):
            ctrl1 = control_wires_reversed[i + 1]
            ctrl2 = work_wires_reversed[i + 1]
            t = work_wires_reversed[i]
            gates.append(qml.Toffoli(wires=[ctrl1, ctrl2, t]))

        return gates
Пример #13
0
class TestCircuitDrawer:
    """Test the CircuitDrawer class."""

    def test_resolve_representation(self, dummy_circuit_drawer):
        """Test that resolve_representation calls the representation resolver with the proper arguments."""

        dummy_circuit_drawer.representation_resolver.element_representation = Mock(
            return_value="Test"
        )

        dummy_circuit_drawer.resolve_representation(Grid(dummy_raw_operation_grid), Grid())

        args_tuples = [
            call[0]
            for call in dummy_circuit_drawer.representation_resolver.element_representation.call_args_list
        ]

        for idx, wire in enumerate(dummy_raw_operation_grid):
            for op in wire:
                assert (op, idx) in args_tuples

    interlocking_multiwire_gate_grid = to_grid(
        [[qml.CNOT(wires=[0, 4]), qml.CNOT(wires=[1, 5]), qml.Toffoli(wires=[2, 3, 6])]], 7
    )
    interlocking_multiwire_gate_representation_grid = Grid(
        [
            ["╭", "", ""],
            ["│", "╭", ""],
            ["│", "│", "╭"],
            ["│", "│", "├"],
            ["╰", "│", "│"],
            ["", "╰", "│"],
            ["", "", "╰"],
        ]
    )

    multiwire_and_single_wire_gate_grid = to_grid(
        [[qml.Toffoli(wires=[0, 3, 4]), qml.PauliX(wires=[1]), qml.Hadamard(wires=[2])]], 5
    )
    multiwire_and_single_wire_gate_representation_grid = Grid([["╭"], ["│"], ["│"], ["├"], ["╰"]])

    all_wire_state_preparation_grid = to_grid(
        [[qml.BasisState(np.array([0, 1, 0, 0, 1, 1]), wires=[0, 1, 2, 3, 4, 5])]], 6
    )
    all_wire_state_preparation_representation_grid = Grid(
        [["╭"], ["├"], ["├"], ["├"], ["├"], ["╰"]]
    )

    multiwire_gate_grid = to_grid(
        [[qml.CNOT(wires=[0, 1]), qml.PauliX(2), qml.CNOT(wires=[3, 4])]], 5
    )

    multiwire_gate_representation_grid = Grid(
        [
            ["╭"],
            ["╰"],
            [""],
            ["╭"],
            ["╰"],
        ]
    )

    multi_and_single_wire_gate_grid = to_grid(
        [
            [
                qml.CNOT(wires=[0, 1]),
                qml.PauliX(2),
                qml.PauliX(4),
                qml.CNOT(wires=[3, 5]),
                qml.Hadamard(6),
            ]
        ],
        7,
    )

    multi_and_single_wire_gate_representation_grid = Grid(
        [
            ["╭"],
            ["╰"],
            [""],
            ["╭"],
            ["│"],
            ["╰"],
            [""],
        ]
    )

    @pytest.mark.parametrize(
        "grid,target_representation_grid",
        [
            (interlocking_multiwire_gate_grid, interlocking_multiwire_gate_representation_grid),
            (
                multiwire_and_single_wire_gate_grid,
                multiwire_and_single_wire_gate_representation_grid,
            ),
            (all_wire_state_preparation_grid, all_wire_state_preparation_representation_grid),
            (multiwire_gate_grid, multiwire_gate_representation_grid),
            (multi_and_single_wire_gate_grid, multi_and_single_wire_gate_representation_grid),
        ],
    )
    def test_resolve_decorations(self, grid, target_representation_grid):
        """Test that decorations are properly resolved."""
        representation_grid = Grid()

        raw_operator_grid = grid.raw_grid
        # make a dummy observable grid
        raw_observable_grid = [[None] for _ in range(len(raw_operator_grid))]

        drawer = CircuitDrawer(raw_operator_grid, raw_observable_grid, Wires(range(10)))

        drawer.resolve_decorations(grid, representation_grid)

        assert_nested_lists_equal(representation_grid.raw_grid, target_representation_grid.raw_grid)

    CNOT04 = qml.CNOT(wires=[0, 4])
    CNOT15 = qml.CNOT(wires=[1, 5])
    Toffoli236 = qml.Toffoli(wires=[2, 3, 6])

    interlocking_CNOT_grid = to_grid([[CNOT04, CNOT15, Toffoli236]], 7)
    moved_interlocking_CNOT_grid = to_grid([[Toffoli236], [CNOT15], [CNOT04]], 7)

    SWAP02 = qml.SWAP(wires=[0, 2])
    SWAP35 = qml.SWAP(wires=[3, 5])
    SWAP14 = qml.SWAP(wires=[1, 4])
    SWAP24 = qml.SWAP(wires=[2, 4])

    interlocking_SWAP_grid = to_grid([[SWAP02, SWAP35, SWAP14], [SWAP24]], 6)
    moved_interlocking_SWAP_grid = to_grid([[SWAP35], [SWAP14], [SWAP02], [SWAP24]], 6)

    @pytest.mark.parametrize(
        "grid,target_grid",
        [
            (interlocking_CNOT_grid, moved_interlocking_CNOT_grid),
            (interlocking_SWAP_grid, moved_interlocking_SWAP_grid),
        ],
    )
    def test_move_multi_wire_gates(self, grid, target_grid):
        """Test that decorations are properly resolved."""

        operator_grid = grid.copy()

        raw_operator_grid = operator_grid.raw_grid
        # make a dummy observable grid
        raw_observable_grid = [[None] for _ in range(len(raw_operator_grid))]

        drawer = CircuitDrawer(raw_operator_grid, raw_observable_grid, Wires(range(10)))
        drawer.move_multi_wire_gates(operator_grid)

        assert_nested_lists_equal(operator_grid.raw_grid, target_grid.raw_grid)
Пример #14
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)
Пример #15
0
    def test_qubit_unitary_decomposition_multiqubit_invalid(self):
        """Test that QubitUnitary is not decomposed for more than two qubits."""
        U = qml.Toffoli(wires=[0, 1, 2]).matrix

        with pytest.raises(NotImplementedError, match="only supported for single- and two-qubit"):
            qml.QubitUnitary.decomposition(U, wires=[0, 1, 2])
Пример #16
0
    def qfunc():
        qml.PauliX(0)
        qml.PauliX(5)
        qml.Toffoli(wires=[5, 1, 0])

        return state()
import pytest

import pennylane as qml
from pennylane.transforms.optimization.optimization_utils import (
    find_next_gate,
    _yzy_to_zyz,
    fuse_rot_angles,
)

from utils import check_matrix_equivalence
from pennylane.transforms.get_unitary_matrix import get_unitary_matrix

sample_op_list = [
    qml.Hadamard(wires="a"),
    qml.CNOT(wires=["a", "b"]),
    qml.Toffoli(wires=[0, 1, "b"]),
    qml.Hadamard(wires="c"),
]


class TestFindNextGate:
    @pytest.mark.parametrize(
        ("wires,op_list,next_gate_idx"),
        [
            ("a", sample_op_list, 0),
            ("b", sample_op_list, 1),
            ("e", sample_op_list, None),
            ([0, 2], sample_op_list, 2),
            ([0, 1], sample_op_list, 2),
            ("c", sample_op_list, 3),
        ],
 def qfunc():
     qml.PauliX(wires="a")
     qml.CNOT(wires=["a", "c"])
     qml.RX(0.2, wires="a")
     qml.Toffoli(wires=["c", "a", "b"])
Пример #19
0
class TestQVMBasic(BaseTest):
    """Unit tests for the QVM simulator."""

    # pylint: disable=protected-access

    def test_identity_expectation(self, shots, qvm, compiler):
        """Test that identity expectation value (i.e. the trace) is 1"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.Identity(wires=[0]))
            O2 = qml.expval(qml.Identity(wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs), dev.expval(O2.obs)])

        # below are the analytic expectation values for this circuit (trace should always be 1)
        self.assertAllAlmostEqual(res,
                                  np.array([1, 1]),
                                  delta=3 / np.sqrt(shots))

    def test_pauliz_expectation(self, shots, qvm, compiler):
        """Test that PauliZ expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.PauliZ(wires=[0]))
            O2 = qml.expval(qml.PauliZ(wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs), dev.expval(O2.obs)])

        # below are the analytic expectation values for this circuit
        self.assertAllAlmostEqual(
            res,
            np.array([np.cos(theta),
                      np.cos(theta) * np.cos(phi)]),
            delta=3 / np.sqrt(shots))

    def test_paulix_expectation(self, shots, qvm, compiler):
        """Test that PauliX expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RY(theta, wires=[0])
            qml.RY(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.PauliX(wires=[0]))
            O2 = qml.expval(qml.PauliX(wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs), dev.expval(O2.obs)])
        # below are the analytic expectation values for this circuit
        self.assertAllAlmostEqual(
            res,
            np.array([np.sin(theta) * np.sin(phi),
                      np.sin(phi)]),
            delta=3 / np.sqrt(shots))

    def test_pauliy_expectation(self, shots, qvm, compiler):
        """Test that PauliY expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.PauliY(wires=[0]))
            O2 = qml.expval(qml.PauliY(wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs), dev.expval(O2.obs)])

        # below are the analytic expectation values for this circuit
        self.assertAllAlmostEqual(res,
                                  np.array([0, -np.cos(theta) * np.sin(phi)]),
                                  delta=3 / np.sqrt(shots))

    def test_hadamard_expectation(self, shots, qvm, compiler):
        """Test that Hadamard expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RY(theta, wires=[0])
            qml.RY(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.Hadamard(wires=[0]))
            O2 = qml.expval(qml.Hadamard(wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs), dev.expval(O2.obs)])

        # below are the analytic expectation values for this circuit
        expected = np.array([
            np.sin(theta) * np.sin(phi) + np.cos(theta),
            np.cos(theta) * np.cos(phi) + np.sin(phi)
        ]) / np.sqrt(2)
        self.assertAllAlmostEqual(res, expected, delta=3 / np.sqrt(shots))

    @flaky(max_runs=10, min_passes=3)
    def test_hermitian_expectation(self, shots, qvm, compiler):
        """Test that arbitrary Hermitian expectation values are correct.

        As the results coming from the qvm are stochastic, a constraint of 3 out of 5 runs was added.
        """

        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RY(theta, wires=[0])
            qml.RY(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.Hermitian(H, wires=[0]))
            O2 = qml.expval(qml.Hermitian(H, wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs), dev.expval(O2.obs)])

        # below are the analytic expectation values for this circuit with arbitrary
        # Hermitian observable H
        a = H[0, 0]
        re_b = H[0, 1].real
        d = H[1, 1]
        ev1 = ((a - d) * np.cos(theta) +
               2 * re_b * np.sin(theta) * np.sin(phi) + a + d) / 2
        ev2 = ((a - d) * np.cos(theta) * np.cos(phi) + 2 * re_b * np.sin(phi) +
               a + d) / 2
        expected = np.array([ev1, ev2])

        self.assertAllAlmostEqual(res, expected, delta=4 / np.sqrt(shots))

    def test_multi_qubit_hermitian_expectation(self, shots, qvm, compiler):
        """Test that arbitrary multi-qubit Hermitian expectation values are correct"""
        theta = 0.432
        phi = 0.123

        A = np.array([
            [-6, 2 + 1j, -3, -5 + 2j],
            [2 - 1j, 0, 2 - 1j, -5 + 4j],
            [-3, 2 + 1j, 0, -4 + 3j],
            [-5 - 2j, -5 - 4j, -4 - 3j, -6],
        ])

        dev = plf.QVMDevice(device="2q-qvm", shots=10 * shots)

        with qml.tape.QuantumTape() as tape:
            qml.RY(theta, wires=[0])
            qml.RY(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.Hermitian(A, wires=[0, 1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs)])
        # below is the analytic expectation value for this circuit with arbitrary
        # Hermitian observable A
        expected = 0.5 * (6 * np.cos(theta) * np.sin(phi) - np.sin(theta) *
                          (8 * np.sin(phi) + 7 * np.cos(phi) + 3) -
                          2 * np.sin(phi) - 6 * np.cos(phi) - 6)

        self.assertAllAlmostEqual(res, expected, delta=5 / np.sqrt(shots))

    def test_var(self, shots, qvm, compiler):
        """Tests for variance calculation"""
        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        phi = 0.543
        theta = 0.6543

        with qml.tape.QuantumTape() as tape:
            qml.RX(phi, wires=[0])
            qml.RY(theta, wires=[0])
            O1 = qml.var(qml.PauliZ(wires=[0]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        var = np.array([dev.var(O1.obs)])
        expected = 0.25 * (3 - np.cos(2 * theta) -
                           2 * np.cos(theta)**2 * np.cos(2 * phi))

        self.assertAlmostEqual(var, expected, delta=3 / np.sqrt(shots))

    def test_var_hermitian(self, shots, qvm, compiler):
        """Tests for variance calculation using an arbitrary Hermitian observable"""
        dev = plf.QVMDevice(device="2q-qvm", shots=100 * shots)

        phi = 0.543
        theta = 0.6543

        A = np.array([[4, -1 + 6j], [-1 - 6j, 2]])

        with qml.tape.QuantumTape() as tape:
            qml.RX(phi, wires=[0])
            qml.RY(theta, wires=[0])
            O1 = qml.var(qml.Hermitian(A, wires=[0]))

        # test correct variance for <A> of a rotated state
        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        var = np.array([dev.var(O1.obs)])
        expected = 0.5 * (2 * np.sin(2 * theta) * np.cos(phi)**2 +
                          24 * np.sin(phi) * np.cos(phi) *
                          (np.sin(theta) - np.cos(theta)) +
                          35 * np.cos(2 * phi) + 39)

        self.assertAlmostEqual(var, expected, delta=0.3)

    @pytest.mark.parametrize(
        "op",
        [
            qml.QubitUnitary(np.array(U), wires=0),
            qml.BasisState(np.array([1, 1, 1]), wires=list(range(3))),
            qml.PauliX(wires=0),
            qml.PauliY(wires=0),
            qml.PauliZ(wires=0),
            qml.S(wires=0),
            qml.T(wires=0),
            qml.RX(0.432, wires=0),
            qml.RY(0.432, wires=0),
            qml.RZ(0.432, wires=0),
            qml.Hadamard(wires=0),
            qml.Rot(0.432, 2, 0.324, wires=0),
            qml.Toffoli(wires=[0, 1, 2]),
            qml.SWAP(wires=[0, 1]),
            qml.CSWAP(wires=[0, 1, 2]),
            qml.CZ(wires=[0, 1]),
            qml.CNOT(wires=[0, 1]),
            qml.PhaseShift(0.432, wires=0),
            qml.CSWAP(wires=[0, 1, 2]),
            plf.CPHASE(0.432, 2, wires=[0, 1]),
            plf.ISWAP(wires=[0, 1]),
            plf.PSWAP(0.432, wires=[0, 1]),
        ],
    )
    def test_apply(self, op, apply_unitary, shots, qvm, compiler):
        """Test the application of gates to a state"""
        dev = plf.QVMDevice(device="3q-qvm",
                            shots=shots,
                            parametric_compilation=False)

        obs = qml.expval(qml.PauliZ(0))

        if op.name == "QubitUnitary":
            state = apply_unitary(U, 3)
        elif op.name == "BasisState":
            state = np.array([0, 0, 0, 0, 0, 0, 0, 1])
        elif op.name == "CPHASE":
            state = apply_unitary(test_operation_map["CPHASE"](0.432, 2), 3)
        elif op.name == "ISWAP":
            state = apply_unitary(test_operation_map["ISWAP"], 3)
        elif op.name == "PSWAP":
            state = apply_unitary(test_operation_map["PSWAP"](0.432), 3)
        else:
            state = apply_unitary(op.matrix, 3)

        with qml.tape.QuantumTape() as tape:
            qml.apply(op)
            obs

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = dev.expval(obs.obs)
        expected = np.vdot(state, np.kron(np.kron(Z, I), I) @ state)

        # verify the device is now in the expected state
        # Note we have increased the tolerance here, since we are only
        # performing 1024 shots.
        self.assertAllAlmostEqual(res, expected, delta=3 / np.sqrt(shots))

    def test_sample_values(self, qvm, tol):
        """Tests if the samples returned by sample have
        the correct values
        """
        dev = plf.QVMDevice(device="1q-qvm", shots=10)

        with qml.tape.QuantumTape() as tape:
            qml.RX(1.5708, wires=[0])
            O1 = qml.expval(qml.PauliZ(wires=[0]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        s1 = dev.sample(O1.obs)

        # s1 should only contain 1 and -1
        self.assertAllAlmostEqual(s1**2, 1, delta=tol)
        self.assertAllAlmostEqual(s1, 1 - 2 * dev._samples[:, 0], delta=tol)

    def test_sample_values_hermitian(self, qvm, tol):
        """Tests if the samples of a Hermitian observable returned by sample have
        the correct values
        """
        theta = 0.543
        shots = 1_000_000
        A = np.array([[1, 2j], [-2j, 0]])

        dev = plf.QVMDevice(device="1q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            O1 = qml.sample(qml.Hermitian(A, wires=[0]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        s1 = dev.sample(O1.obs)

        # s1 should only contain the eigenvalues of
        # the hermitian matrix
        eigvals = np.linalg.eigvalsh(A)
        assert np.allclose(sorted(list(set(s1))),
                           sorted(eigvals),
                           atol=tol,
                           rtol=0)

        # the analytic mean is 2*sin(theta)+0.5*cos(theta)+0.5
        assert np.allclose(np.mean(s1),
                           2 * np.sin(theta) + 0.5 * np.cos(theta) + 0.5,
                           atol=0.1,
                           rtol=0)

        # the analytic variance is 0.25*(sin(theta)-4*cos(theta))^2
        assert np.allclose(np.var(s1),
                           0.25 * (np.sin(theta) - 4 * np.cos(theta))**2,
                           atol=0.1,
                           rtol=0)

    def test_sample_values_hermitian_multi_qubit(self, qvm, tol):
        """Tests if the samples of a multi-qubit Hermitian observable returned by sample have
        the correct values
        """
        theta = 0.543
        shots = 100_000

        A = np.array([
            [1, 2j, 1 - 2j, 0.5j],
            [-2j, 0, 3 + 4j, 1],
            [1 + 2j, 3 - 4j, 0.75, 1.5 - 2j],
            [-0.5j, 1, 1.5 + 2j, -1],
        ])

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            qml.RY(2 * theta, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.sample(qml.Hermitian(A, wires=[0, 1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        s1 = dev.sample(O1.obs)

        # s1 should only contain the eigenvalues of
        # the hermitian matrix
        eigvals = np.linalg.eigvalsh(A)
        assert np.allclose(sorted(list(set(s1))),
                           sorted(eigvals),
                           atol=tol,
                           rtol=0)

        # make sure the mean matches the analytic mean
        expected = (88 * np.sin(theta) + 24 * np.sin(2 * theta) -
                    40 * np.sin(3 * theta) + 5 * np.cos(theta) -
                    6 * np.cos(2 * theta) + 27 * np.cos(3 * theta) + 6) / 32
        assert np.allclose(np.mean(s1), expected, atol=0.1, rtol=0)

    def test_wires_argument(self):
        """Test that the wires argument gets processed correctly."""

        dev_no_wires = plf.QVMDevice(device="2q-qvm", shots=5)
        assert dev_no_wires.wires == Wires(range(2))

        with pytest.raises(ValueError, match="Device has a fixed number of"):
            plf.QVMDevice(device="2q-qvm", shots=5, wires=1000)

        dev_iterable_wires = plf.QVMDevice(device="2q-qvm",
                                           shots=5,
                                           wires=range(2))
        assert dev_iterable_wires.wires == Wires(range(2))

        with pytest.raises(ValueError, match="Device has a fixed number of"):
            plf.QVMDevice(device="2q-qvm", shots=5, wires=range(1000))

    @pytest.mark.parametrize("shots", list(range(0, -10, -1)))
    def test_raise_error_if_shots_is_not_positive(self, shots):
        """Test that instantiating a QVMDevice if the number of shots is not a postivie
        integer raises an error"""
        with pytest.raises(
                ValueError,
                match="Number of shots must be a positive integer."):
            dev = plf.QVMDevice(device="2q-qvm", shots=shots)

    def test_raise_error_if_shots_is_none(self, shots):
        """Test that instantiating a QVMDevice to be used for analytic computations raises an error"""
        with pytest.raises(
                ValueError,
                match="QVM device cannot be used for analytic computations."):
            dev = plf.QVMDevice(device="2q-qvm", shots=None)

    @pytest.mark.parametrize(
        "device", ["2q-qvm", np.random.choice(TEST_QPU_LATTICES)])
    def test_timeout_set_correctly(self, shots, device):
        """Test that the timeout attrbiute for the QuantumComputer stored by the QVMDevice
        is set correctly when passing a value as keyword argument"""
        dev = plf.QVMDevice(device=device, shots=shots, timeout=100)
        assert dev.qc.compiler.client.timeout == 100

    @pytest.mark.parametrize(
        "device", ["2q-qvm", np.random.choice(TEST_QPU_LATTICES)])
    def test_timeout_default(self, shots, device):
        """Test that the timeout attrbiute for the QuantumComputer stored by the QVMDevice
        is set correctly when passing a value as keyword argument"""
        dev = plf.QVMDevice(device=device, shots=shots)
        qc = pyquil.get_qc(device, as_qvm=True)

        # Check that the timeouts are equal (it has not been changed as a side effect of
        # instantiation
        assert dev.qc.compiler.client.timeout == qc.compiler.client.timeout

    def test_compiled_program_stored(self, qvm, monkeypatch):
        """Test that QVM device stores the latest compiled program."""
        dev = qml.device("forest.qvm", device="2q-qvm")

        dev.compiled_program is None

        theta = 0.432
        phi = 0.123

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.Identity(wires=[0]))
            O2 = qml.expval(qml.Identity(wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev.generate_samples()

        dev.compiled_program is not None

    def test_stored_compiled_program_correct(self, qvm, monkeypatch):
        """Test that QVM device stores the latest compiled program."""
        dev = qml.device("forest.qvm", device="2q-qvm")

        dev.compiled_program is None

        theta = 0.432

        with qml.tape.QuantumTape() as tape:
            qml.RZ(theta, wires=[0])
            qml.CZ(wires=[0, 1])
            O1 = qml.expval(qml.PauliZ(wires=[0]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev.generate_samples()

        dev.compiled_program.program == compiled_program
Пример #20
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]),
    "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)
Пример #21
0
    (qml.Hadamard(0), "H", "H"),
    (qml.PauliX(0), "X", "X"),
    (qml.PauliY(0), "Y", "Y"),
    (qml.PauliZ(0), "Z", "Z"),
    (qml.S(wires=0), "S", "S⁻¹"),
    (qml.T(wires=0), "T", "T⁻¹"),
    (qml.SX(wires=0), "SX", "SX⁻¹"),
    (qml.CNOT(wires=(0, 1)), "⊕", "⊕"),
    (qml.CZ(wires=(0, 1)), "Z", "Z"),
    (qml.CY(wires=(0, 1)), "Y", "Y"),
    (qml.SWAP(wires=(0, 1)), "SWAP", "SWAP⁻¹"),
    (qml.ISWAP(wires=(0, 1)), "ISWAP", "ISWAP⁻¹"),
    (qml.SISWAP(wires=(0, 1)), "SISWAP", "SISWAP⁻¹"),
    (qml.SQISW(wires=(0, 1)), "SISWAP", "SISWAP⁻¹"),
    (qml.CSWAP(wires=(0, 1, 2)), "SWAP", "SWAP"),
    (qml.Toffoli(wires=(0, 1, 2)), "⊕", "⊕"),
    (qml.MultiControlledX(control_wires=(0, 1, 2), wires=(3)), "⊕", "⊕"),
    (qml.Barrier(0), "||", "||"),
    (qml.WireCut(wires=0), "//", "//"),
]


@pytest.mark.parametrize("op, label1, label2", label_data)
def test_label_method(op, label1, label2):
    assert op.label() == label1
    assert op.label(decimals=2) == label1

    op.inv()
    assert op.label() == label2

Пример #22
0
 def circuit(x, y):
     qml.RX(x[0], wires=0)
     qml.Toffoli(wires=(0, 1, 2))
     qml.CRY(x[1], wires=(0, 1))
     qml.Rot(x[2], x[3], y, wires=2)
     return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliX(1))
Пример #23
0
 def circuitz():
     qml.Hadamard(wires=0)
     qml.Hadamard(wires=1)
     qml.Hadamard(wires=2)
     qml.Toffoli(wires=[0, 1, 2])
     return qml.expval(qml.PauliZ(2))
Пример #24
0
    ax.annotate("CSWAP",
                xy=(2, 2.5),
                xycoords='data',
                xytext=(2.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.templates.GroverOperator(wires=(0, 1, 2, 3))
        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)
    mpl_style(tape)
    rcparams(tape)
    wires_and_labels(tape)
    postprocessing(tape)
 def expand(self):
     with qml.tape.QuantumTape() as tape:
         qml.Toffoli(wires=[self.wires[0],self.wires[2],self.wires[3]])
         qml.CNOT(wires=[self.wires[1],self.wires[2]])
         qml.Toffoli(wires=self.wires[1:])
     return tape
Пример #26
0
    def qfunc():
        qml.PauliX(0)
        qml.PauliX(5)
        qml.Toffoli(wires=[5, 1, 0])

        return [qml.expval(qml.PauliY(0)), qml.probs(wires=[1, 2, 4])]
Пример #27
0
 def f2():
     qml.QubitUnitary(U1, wires=range(3))
     qml.Toffoli(wires=control_wires + [target_wire])
     qml.QubitUnitary(U2, wires=range(3))
     return qml.state()
Пример #28
0
 def oracle():
     qml.Hadamard(wires[-1])
     qml.Toffoli(wires=wires)
     qml.Hadamard(wires[-1])
class TestRepresentationResolver:
    """Test the RepresentationResolver class."""
    @pytest.mark.parametrize(
        "list,element,index,list_after",
        [
            ([1, 2, 3], 2, 1, [1, 2, 3]),
            ([1, 2, 2, 3], 2, 1, [1, 2, 2, 3]),
            ([1, 2, 3], 4, 3, [1, 2, 3, 4]),
        ],
    )
    def test_index_of_array_or_append(self, list, element, index, list_after):
        """Test the method index_of_array_or_append."""

        assert RepresentationResolver.index_of_array_or_append(element,
                                                               list) == index
        assert list == list_after

    @pytest.mark.parametrize(
        "par,expected",
        [
            (3, "3"),
            (5.236422, "5.24"),
        ],
    )
    def test_single_parameter_representation(self,
                                             unicode_representation_resolver,
                                             par, expected):
        """Test that single parameters are properly resolved."""
        assert unicode_representation_resolver.single_parameter_representation(
            par) == expected

    @pytest.mark.parametrize(
        "op,wire,target",
        [
            (qml.PauliX(wires=[1]), 1, "X"),
            (qml.CNOT(wires=[0, 1]), 1, "X"),
            (qml.CNOT(wires=[0, 1]), 0, "C"),
            (qml.Toffoli(wires=[0, 2, 1]), 1, "X"),
            (qml.Toffoli(wires=[0, 2, 1]), 0, "C"),
            (qml.Toffoli(wires=[0, 2, 1]), 2, "C"),
            (qml.CSWAP(wires=[0, 2, 1]), 1, "SWAP"),
            (qml.CSWAP(wires=[0, 2, 1]), 2, "SWAP"),
            (qml.CSWAP(wires=[0, 2, 1]), 0, "C"),
            (qml.PauliY(wires=[1]), 1, "Y"),
            (qml.PauliZ(wires=[1]), 1, "Z"),
            (qml.CZ(wires=[0, 1]), 1, "Z"),
            (qml.CZ(wires=[0, 1]), 0, "C"),
            (qml.Identity(wires=[1]), 1, "I"),
            (qml.Hadamard(wires=[1]), 1, "H"),
            (qml.PauliRot(3.14, "XX", wires=[0, 1]), 1, "RX(3.14)"),
            (qml.PauliRot(3.14, "YZ", wires=[0, 1]), 1, "RZ(3.14)"),
            (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4
                                                ]), 0, "RI(3.14)"),
            (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4
                                                ]), 1, "RX(3.14)"),
            (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4
                                                ]), 2, "RY(3.14)"),
            (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4
                                                ]), 3, "RZ(3.14)"),
            (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4
                                                ]), 4, "RI(3.14)"),
            (qml.MultiRZ(3.14, wires=[0, 1]), 0, "RZ(3.14)"),
            (qml.MultiRZ(3.14, wires=[0, 1]), 1, "RZ(3.14)"),
            (qml.CRX(3.14, wires=[0, 1]), 1, "RX(3.14)"),
            (qml.CRX(3.14, wires=[0, 1]), 0, "C"),
            (qml.CRY(3.14, wires=[0, 1]), 1, "RY(3.14)"),
            (qml.CRY(3.14, wires=[0, 1]), 0, "C"),
            (qml.CRZ(3.14, wires=[0, 1]), 1, "RZ(3.14)"),
            (qml.CRZ(3.14, wires=[0, 1]), 0, "C"),
            (qml.CRot(3.14, 2.14, 1.14, wires=[0, 1
                                               ]), 1, "Rot(3.14, 2.14, 1.14)"),
            (qml.CRot(3.14, 2.14, 1.14, wires=[0, 1]), 0, "C"),
            (qml.PhaseShift(3.14, wires=[0]), 0, "Rϕ(3.14)"),
            (qml.Beamsplitter(1, 2, wires=[0, 1]), 1, "BS(1, 2)"),
            (qml.Beamsplitter(1, 2, wires=[0, 1]), 0, "BS(1, 2)"),
            (qml.Squeezing(1, 2, wires=[1]), 1, "S(1, 2)"),
            (qml.TwoModeSqueezing(1, 2, wires=[0, 1]), 1, "S(1, 2)"),
            (qml.TwoModeSqueezing(1, 2, wires=[0, 1]), 0, "S(1, 2)"),
            (qml.Displacement(1, 2, wires=[1]), 1, "D(1, 2)"),
            (qml.NumberOperator(wires=[1]), 1, "n"),
            (qml.Rotation(3.14, wires=[1]), 1, "R(3.14)"),
            (qml.ControlledAddition(3.14, wires=[0, 1]), 1, "X(3.14)"),
            (qml.ControlledAddition(3.14, wires=[0, 1]), 0, "C"),
            (qml.ControlledPhase(3.14, wires=[0, 1]), 1, "Z(3.14)"),
            (qml.ControlledPhase(3.14, wires=[0, 1]), 0, "C"),
            (qml.ThermalState(3, wires=[1]), 1, "Thermal(3)"),
            (
                qml.GaussianState(np.array([[2, 0], [0, 2]]),
                                  np.array([1, 2]),
                                  wires=[1]),
                1,
                "Gaussian(M0,M1)",
            ),
            (qml.QuadraticPhase(3.14, wires=[1]), 1, "P(3.14)"),
            (qml.RX(3.14, wires=[1]), 1, "RX(3.14)"),
            (qml.S(wires=[2]), 2, "S"),
            (qml.T(wires=[2]), 2, "T"),
            (qml.RX(3.14, wires=[1]), 1, "RX(3.14)"),
            (qml.RY(3.14, wires=[1]), 1, "RY(3.14)"),
            (qml.RZ(3.14, wires=[1]), 1, "RZ(3.14)"),
            (qml.Rot(3.14, 2.14, 1.14, wires=[1]), 1, "Rot(3.14, 2.14, 1.14)"),
            (qml.U1(3.14, wires=[1]), 1, "U1(3.14)"),
            (qml.U2(3.14, 2.14, wires=[1]), 1, "U2(3.14, 2.14)"),
            (qml.U3(3.14, 2.14, 1.14, wires=[1]), 1, "U3(3.14, 2.14, 1.14)"),
            (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 1, "|0⟩"),
            (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 2, "|1⟩"),
            (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 3, "|0⟩"),
            (qml.QubitStateVector(np.array([0, 1, 0, 0]),
                                  wires=[1, 2]), 1, "QubitStateVector(M0)"),
            (qml.QubitStateVector(np.array([0, 1, 0, 0]),
                                  wires=[1, 2]), 2, "QubitStateVector(M0)"),
            (qml.QubitUnitary(np.eye(2), wires=[1]), 1, "U0"),
            (qml.QubitUnitary(np.eye(4), wires=[1, 2]), 2, "U0"),
            (qml.Kerr(3.14, wires=[1]), 1, "Kerr(3.14)"),
            (qml.CrossKerr(3.14, wires=[1, 2]), 1, "CrossKerr(3.14)"),
            (qml.CrossKerr(3.14, wires=[1, 2]), 2, "CrossKerr(3.14)"),
            (qml.CubicPhase(3.14, wires=[1]), 1, "V(3.14)"),
            (qml.InterferometerUnitary(
                np.eye(4), wires=[1, 3]), 1, "InterferometerUnitary(M0)"),
            (qml.InterferometerUnitary(
                np.eye(4), wires=[1, 3]), 3, "InterferometerUnitary(M0)"),
            (qml.CatState(3.14, 2.14, 1,
                          wires=[1]), 1, "CatState(3.14, 2.14, 1)"),
            (qml.CoherentState(3.14, 2.14,
                               wires=[1]), 1, "CoherentState(3.14, 2.14)"),
            (
                qml.FockDensityMatrix(np.kron(np.eye(4), np.eye(4)),
                                      wires=[1, 2]),
                1,
                "FockDensityMatrix(M0)",
            ),
            (
                qml.FockDensityMatrix(np.kron(np.eye(4), np.eye(4)),
                                      wires=[1, 2]),
                2,
                "FockDensityMatrix(M0)",
            ),
            (
                qml.DisplacedSqueezedState(3.14, 2.14, 1.14, 0.14, wires=[1]),
                1,
                "DisplacedSqueezedState(3.14, 2.14, 1.14, 0.14)",
            ),
            (qml.FockState(7, wires=[1]), 1, "|7⟩"),
            (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3
                                                             ]), 1, "|4⟩"),
            (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3
                                                             ]), 2, "|5⟩"),
            (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3
                                                             ]), 3, "|7⟩"),
            (qml.SqueezedState(3.14, 2.14,
                               wires=[1]), 1, "SqueezedState(3.14, 2.14)"),
            (qml.Hermitian(np.eye(4), wires=[1, 2]), 1, "H0"),
            (qml.Hermitian(np.eye(4), wires=[1, 2]), 2, "H0"),
            (qml.X(wires=[1]), 1, "x"),
            (qml.P(wires=[1]), 1, "p"),
            (qml.FockStateProjector(np.array([4, 5, 7]),
                                    wires=[1, 2, 3]), 1, "|4,5,7╳4,5,7|"),
            (
                qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1]),
                2,
                "1+2x₀-1.3x₁+6p₁",
            ),
            (
                qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5],
                                     [-1.3, 4.5, 2.3]]),
                           wires=[1]),
                1,
                "1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀",
            ),
            (
                qml.PolyXP(
                    np.array([
                        [1.2, 2.3, 4.5, 0, 0],
                        [-1.2, 1.2, -1.5, 0, 0],
                        [-1.3, 4.5, 2.3, 0, 0],
                        [0, 2.6, 0, 0, 0],
                        [0, 0, 0, -4.7, -1.0],
                    ]),
                    wires=[1],
                ),
                1,
                "1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀+2.6x₀x₁-p₁²-4.7x₁p₁",
            ),
            (qml.QuadOperator(3.14, wires=[1]), 1, "cos(3.14)x+sin(3.14)p"),
            (qml.PauliX(wires=[1]).inv(), 1, "X⁻¹"),
            (qml.CNOT(wires=[0, 1]).inv(), 1, "X⁻¹"),
            (qml.CNOT(wires=[0, 1]).inv(), 0, "C"),
            (qml.Toffoli(wires=[0, 2, 1]).inv(), 1, "X⁻¹"),
            (qml.Toffoli(wires=[0, 2, 1]).inv(), 0, "C"),
            (qml.Toffoli(wires=[0, 2, 1]).inv(), 2, "C"),
            (qml.measure.sample(wires=[0, 1]), 0,
             "basis"),  # not providing an observable in
            (qml.measure.sample(wires=[0, 1]), 1,
             "basis"),  # sample gets displayed as raw
            (two_wire_quantum_tape(), 0, "QuantumTape:T0"),
            (two_wire_quantum_tape(), 1, "QuantumTape:T0"),
        ],
    )
    def test_operator_representation_unicode(self,
                                             unicode_representation_resolver,
                                             op, wire, target):
        """Test that an Operator instance is properly resolved."""
        assert unicode_representation_resolver.operator_representation(
            op, wire) == target

    @pytest.mark.parametrize(
        "op,wire,target",
        [
            (qml.PauliX(wires=[1]), 1, "X"),
            (qml.CNOT(wires=[0, 1]), 1, "X"),
            (qml.CNOT(wires=[0, 1]), 0, "C"),
            (qml.Toffoli(wires=[0, 2, 1]), 1, "X"),
            (qml.Toffoli(wires=[0, 2, 1]), 0, "C"),
            (qml.Toffoli(wires=[0, 2, 1]), 2, "C"),
            (qml.CSWAP(wires=[0, 2, 1]), 1, "SWAP"),
            (qml.CSWAP(wires=[0, 2, 1]), 2, "SWAP"),
            (qml.CSWAP(wires=[0, 2, 1]), 0, "C"),
            (qml.PauliY(wires=[1]), 1, "Y"),
            (qml.PauliZ(wires=[1]), 1, "Z"),
            (qml.CZ(wires=[0, 1]), 1, "Z"),
            (qml.CZ(wires=[0, 1]), 0, "C"),
            (qml.Identity(wires=[1]), 1, "I"),
            (qml.Hadamard(wires=[1]), 1, "H"),
            (qml.CRX(3.14, wires=[0, 1]), 1, "RX(3.14)"),
            (qml.CRX(3.14, wires=[0, 1]), 0, "C"),
            (qml.CRY(3.14, wires=[0, 1]), 1, "RY(3.14)"),
            (qml.CRY(3.14, wires=[0, 1]), 0, "C"),
            (qml.CRZ(3.14, wires=[0, 1]), 1, "RZ(3.14)"),
            (qml.CRZ(3.14, wires=[0, 1]), 0, "C"),
            (qml.CRot(3.14, 2.14, 1.14, wires=[0, 1
                                               ]), 1, "Rot(3.14, 2.14, 1.14)"),
            (qml.CRot(3.14, 2.14, 1.14, wires=[0, 1]), 0, "C"),
            (qml.PhaseShift(3.14, wires=[0]), 0, "Rϕ(3.14)"),
            (qml.Beamsplitter(1, 2, wires=[0, 1]), 1, "BS(1, 2)"),
            (qml.Beamsplitter(1, 2, wires=[0, 1]), 0, "BS(1, 2)"),
            (qml.Squeezing(1, 2, wires=[1]), 1, "S(1, 2)"),
            (qml.TwoModeSqueezing(1, 2, wires=[0, 1]), 1, "S(1, 2)"),
            (qml.TwoModeSqueezing(1, 2, wires=[0, 1]), 0, "S(1, 2)"),
            (qml.Displacement(1, 2, wires=[1]), 1, "D(1, 2)"),
            (qml.NumberOperator(wires=[1]), 1, "n"),
            (qml.Rotation(3.14, wires=[1]), 1, "R(3.14)"),
            (qml.ControlledAddition(3.14, wires=[0, 1]), 1, "X(3.14)"),
            (qml.ControlledAddition(3.14, wires=[0, 1]), 0, "C"),
            (qml.ControlledPhase(3.14, wires=[0, 1]), 1, "Z(3.14)"),
            (qml.ControlledPhase(3.14, wires=[0, 1]), 0, "C"),
            (qml.ThermalState(3, wires=[1]), 1, "Thermal(3)"),
            (
                qml.GaussianState(np.array([[2, 0], [0, 2]]),
                                  np.array([1, 2]),
                                  wires=[1]),
                1,
                "Gaussian(M0,M1)",
            ),
            (qml.QuadraticPhase(3.14, wires=[1]), 1, "P(3.14)"),
            (qml.RX(3.14, wires=[1]), 1, "RX(3.14)"),
            (qml.S(wires=[2]), 2, "S"),
            (qml.T(wires=[2]), 2, "T"),
            (qml.RX(3.14, wires=[1]), 1, "RX(3.14)"),
            (qml.RY(3.14, wires=[1]), 1, "RY(3.14)"),
            (qml.RZ(3.14, wires=[1]), 1, "RZ(3.14)"),
            (qml.Rot(3.14, 2.14, 1.14, wires=[1]), 1, "Rot(3.14, 2.14, 1.14)"),
            (qml.U1(3.14, wires=[1]), 1, "U1(3.14)"),
            (qml.U2(3.14, 2.14, wires=[1]), 1, "U2(3.14, 2.14)"),
            (qml.U3(3.14, 2.14, 1.14, wires=[1]), 1, "U3(3.14, 2.14, 1.14)"),
            (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 1, "|0>"),
            (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 2, "|1>"),
            (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 3, "|0>"),
            (qml.QubitStateVector(np.array([0, 1, 0, 0]),
                                  wires=[1, 2]), 1, "QubitStateVector(M0)"),
            (qml.QubitStateVector(np.array([0, 1, 0, 0]),
                                  wires=[1, 2]), 2, "QubitStateVector(M0)"),
            (qml.QubitUnitary(np.eye(2), wires=[1]), 1, "U0"),
            (qml.QubitUnitary(np.eye(4), wires=[1, 2]), 2, "U0"),
            (qml.Kerr(3.14, wires=[1]), 1, "Kerr(3.14)"),
            (qml.CrossKerr(3.14, wires=[1, 2]), 1, "CrossKerr(3.14)"),
            (qml.CrossKerr(3.14, wires=[1, 2]), 2, "CrossKerr(3.14)"),
            (qml.CubicPhase(3.14, wires=[1]), 1, "V(3.14)"),
            (qml.InterferometerUnitary(
                np.eye(4), wires=[1, 3]), 1, "InterferometerUnitary(M0)"),
            (qml.InterferometerUnitary(
                np.eye(4), wires=[1, 3]), 3, "InterferometerUnitary(M0)"),
            (qml.CatState(3.14, 2.14, 1,
                          wires=[1]), 1, "CatState(3.14, 2.14, 1)"),
            (qml.CoherentState(3.14, 2.14,
                               wires=[1]), 1, "CoherentState(3.14, 2.14)"),
            (
                qml.FockDensityMatrix(np.kron(np.eye(4), np.eye(4)),
                                      wires=[1, 2]),
                1,
                "FockDensityMatrix(M0)",
            ),
            (
                qml.FockDensityMatrix(np.kron(np.eye(4), np.eye(4)),
                                      wires=[1, 2]),
                2,
                "FockDensityMatrix(M0)",
            ),
            (
                qml.DisplacedSqueezedState(3.14, 2.14, 1.14, 0.14, wires=[1]),
                1,
                "DisplacedSqueezedState(3.14, 2.14, 1.14, 0.14)",
            ),
            (qml.FockState(7, wires=[1]), 1, "|7>"),
            (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3
                                                             ]), 1, "|4>"),
            (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3
                                                             ]), 2, "|5>"),
            (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3
                                                             ]), 3, "|7>"),
            (qml.SqueezedState(3.14, 2.14,
                               wires=[1]), 1, "SqueezedState(3.14, 2.14)"),
            (qml.Hermitian(np.eye(4), wires=[1, 2]), 1, "H0"),
            (qml.Hermitian(np.eye(4), wires=[1, 2]), 2, "H0"),
            (qml.X(wires=[1]), 1, "x"),
            (qml.P(wires=[1]), 1, "p"),
            (qml.FockStateProjector(np.array([4, 5, 7]),
                                    wires=[1, 2, 3]), 1, "|4,5,7X4,5,7|"),
            (
                qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1]),
                2,
                "1+2x_0-1.3x_1+6p_1",
            ),
            (
                qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5],
                                     [-1.3, 4.5, 2.3]]),
                           wires=[1]),
                1,
                "1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0",
            ),
            (
                qml.PolyXP(
                    np.array([
                        [1.2, 2.3, 4.5, 0, 0],
                        [-1.2, 1.2, -1.5, 0, 0],
                        [-1.3, 4.5, 2.3, 0, 0],
                        [0, 2.6, 0, 0, 0],
                        [0, 0, 0, -4.7, 0],
                    ]),
                    wires=[1],
                ),
                1,
                "1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0+2.6x_0x_1-4.7x_1p_1",
            ),
            (qml.QuadOperator(3.14, wires=[1]), 1, "cos(3.14)x+sin(3.14)p"),
            (qml.QuadOperator(3.14, wires=[1]), 1, "cos(3.14)x+sin(3.14)p"),
            (qml.PauliX(wires=[1]).inv(), 1, "X^-1"),
            (qml.CNOT(wires=[0, 1]).inv(), 1, "X^-1"),
            (qml.CNOT(wires=[0, 1]).inv(), 0, "C"),
            (qml.Toffoli(wires=[0, 2, 1]).inv(), 1, "X^-1"),
            (qml.Toffoli(wires=[0, 2, 1]).inv(), 0, "C"),
            (qml.Toffoli(wires=[0, 2, 1]).inv(), 2, "C"),
            (qml.measure.sample(wires=[0, 1]), 0,
             "basis"),  # not providing an observable in
            (qml.measure.sample(wires=[0, 1]), 1,
             "basis"),  # sample gets displayed as raw
            (two_wire_quantum_tape(), 0, "QuantumTape:T0"),
            (two_wire_quantum_tape(), 1, "QuantumTape:T0"),
        ],
    )
    def test_operator_representation_ascii(self, ascii_representation_resolver,
                                           op, wire, target):
        """Test that an Operator instance is properly resolved."""
        assert ascii_representation_resolver.operator_representation(
            op, wire) == target

    @pytest.mark.parametrize(
        "obs,wire,target",
        [
            (qml.expval(qml.PauliX(wires=[1])), 1, "⟨X⟩"),
            (qml.expval(qml.PauliY(wires=[1])), 1, "⟨Y⟩"),
            (qml.expval(qml.PauliZ(wires=[1])), 1, "⟨Z⟩"),
            (qml.expval(qml.Hadamard(wires=[1])), 1, "⟨H⟩"),
            (qml.expval(qml.Hermitian(np.eye(4), wires=[1, 2])), 1, "⟨H0⟩"),
            (qml.expval(qml.Hermitian(np.eye(4), wires=[1, 2])), 2, "⟨H0⟩"),
            (qml.expval(qml.NumberOperator(wires=[1])), 1, "⟨n⟩"),
            (qml.expval(qml.X(wires=[1])), 1, "⟨x⟩"),
            (qml.expval(qml.P(wires=[1])), 1, "⟨p⟩"),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])),
                1,
                "⟨|4,5,7╳4,5,7|⟩",
            ),
            (
                qml.expval(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1
                                                                           ])),
                2,
                "⟨1+2x₀-1.3x₁+6p₁⟩",
            ),
            (
                qml.expval(
                    qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5],
                                         [-1.3, 4.5, 2.3]]),
                               wires=[1])),
                1,
                "⟨1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀⟩",
            ),
            (qml.expval(qml.QuadOperator(
                3.14, wires=[1])), 1, "⟨cos(3.14)x+sin(3.14)p⟩"),
            (qml.var(qml.PauliX(wires=[1])), 1, "Var[X]"),
            (qml.var(qml.PauliY(wires=[1])), 1, "Var[Y]"),
            (qml.var(qml.PauliZ(wires=[1])), 1, "Var[Z]"),
            (qml.var(qml.Hadamard(wires=[1])), 1, "Var[H]"),
            (qml.var(qml.Hermitian(np.eye(4), wires=[1, 2])), 1, "Var[H0]"),
            (qml.var(qml.Hermitian(np.eye(4), wires=[1, 2])), 2, "Var[H0]"),
            (qml.var(qml.NumberOperator(wires=[1])), 1, "Var[n]"),
            (qml.var(qml.X(wires=[1])), 1, "Var[x]"),
            (qml.var(qml.P(wires=[1])), 1, "Var[p]"),
            (
                qml.var(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])),
                1,
                "Var[|4,5,7╳4,5,7|]",
            ),
            (
                qml.var(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1])),
                2,
                "Var[1+2x₀-1.3x₁+6p₁]",
            ),
            (
                qml.var(
                    qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5],
                                         [-1.3, 4.5, 2.3]]),
                               wires=[1])),
                1,
                "Var[1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀]",
            ),
            (qml.var(qml.QuadOperator(
                3.14, wires=[1])), 1, "Var[cos(3.14)x+sin(3.14)p]"),
            (qml.sample(qml.PauliX(wires=[1])), 1, "Sample[X]"),
            (qml.sample(qml.PauliY(wires=[1])), 1, "Sample[Y]"),
            (qml.sample(qml.PauliZ(wires=[1])), 1, "Sample[Z]"),
            (qml.sample(qml.Hadamard(wires=[1])), 1, "Sample[H]"),
            (qml.sample(qml.Hermitian(np.eye(4), wires=[1, 2
                                                        ])), 1, "Sample[H0]"),
            (qml.sample(qml.Hermitian(np.eye(4), wires=[1, 2
                                                        ])), 2, "Sample[H0]"),
            (qml.sample(qml.NumberOperator(wires=[1])), 1, "Sample[n]"),
            (qml.sample(qml.X(wires=[1])), 1, "Sample[x]"),
            (qml.sample(qml.P(wires=[1])), 1, "Sample[p]"),
            (
                qml.sample(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])),
                1,
                "Sample[|4,5,7╳4,5,7|]",
            ),
            (
                qml.sample(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1
                                                                           ])),
                2,
                "Sample[1+2x₀-1.3x₁+6p₁]",
            ),
            (
                qml.sample(
                    qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5],
                                         [-1.3, 4.5, 2.3]]),
                               wires=[1])),
                1,
                "Sample[1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀]",
            ),
            (qml.sample(qml.QuadOperator(
                3.14, wires=[1])), 1, "Sample[cos(3.14)x+sin(3.14)p]"),
            (
                qml.expval(
                    qml.PauliX(wires=[1]) @ qml.PauliY(wires=[2])
                    @ qml.PauliZ(wires=[3])),
                1,
                "⟨X ⊗ Y ⊗ Z⟩",
            ),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])
                    @ qml.X(wires=[4])),
                1,
                "⟨|4,5,7╳4,5,7| ⊗ x⟩",
            ),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])
                    @ qml.X(wires=[4])),
                2,
                "⟨|4,5,7╳4,5,7| ⊗ x⟩",
            ),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])
                    @ qml.X(wires=[4])),
                3,
                "⟨|4,5,7╳4,5,7| ⊗ x⟩",
            ),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])
                    @ qml.X(wires=[4])),
                4,
                "⟨|4,5,7╳4,5,7| ⊗ x⟩",
            ),
            (
                qml.sample(
                    qml.Hermitian(np.eye(4), wires=[1, 2]) @ qml.Hermitian(
                        np.eye(4), wires=[0, 3])),
                0,
                "Sample[H0 ⊗ H0]",
            ),
            (
                qml.sample(
                    qml.Hermitian(np.eye(4), wires=[1, 2]) @ qml.Hermitian(
                        2 * np.eye(4), wires=[0, 3])),
                0,
                "Sample[H0 ⊗ H1]",
            ),
            (qml.probs([0]), 0, "Probs"),
            (state(), 0, "State"),
        ],
    )
    def test_output_representation_unicode(self,
                                           unicode_representation_resolver,
                                           obs, wire, target):
        """Test that an Observable instance with return type is properly resolved."""
        assert unicode_representation_resolver.output_representation(
            obs, wire) == target

    def test_fallback_output_representation_unicode(
            self, unicode_representation_resolver):
        """Test that an Observable instance with return type is properly resolved."""
        obs = qml.PauliZ(0)
        obs.return_type = "TestReturnType"

        assert unicode_representation_resolver.output_representation(
            obs, 0) == "TestReturnType[Z]"

    @pytest.mark.parametrize(
        "obs,wire,target",
        [
            (qml.expval(qml.PauliX(wires=[1])), 1, "<X>"),
            (qml.expval(qml.PauliY(wires=[1])), 1, "<Y>"),
            (qml.expval(qml.PauliZ(wires=[1])), 1, "<Z>"),
            (qml.expval(qml.Hadamard(wires=[1])), 1, "<H>"),
            (qml.expval(qml.Hermitian(np.eye(4), wires=[1, 2])), 1, "<H0>"),
            (qml.expval(qml.Hermitian(np.eye(4), wires=[1, 2])), 2, "<H0>"),
            (qml.expval(qml.NumberOperator(wires=[1])), 1, "<n>"),
            (qml.expval(qml.X(wires=[1])), 1, "<x>"),
            (qml.expval(qml.P(wires=[1])), 1, "<p>"),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])),
                1,
                "<|4,5,7X4,5,7|>",
            ),
            (
                qml.expval(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1
                                                                           ])),
                2,
                "<1+2x_0-1.3x_1+6p_1>",
            ),
            (
                qml.expval(
                    qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5],
                                         [-1.3, 4.5, 2.3]]),
                               wires=[1])),
                1,
                "<1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0>",
            ),
            (qml.expval(qml.QuadOperator(
                3.14, wires=[1])), 1, "<cos(3.14)x+sin(3.14)p>"),
            (qml.var(qml.PauliX(wires=[1])), 1, "Var[X]"),
            (qml.var(qml.PauliY(wires=[1])), 1, "Var[Y]"),
            (qml.var(qml.PauliZ(wires=[1])), 1, "Var[Z]"),
            (qml.var(qml.Hadamard(wires=[1])), 1, "Var[H]"),
            (qml.var(qml.Hermitian(np.eye(4), wires=[1, 2])), 1, "Var[H0]"),
            (qml.var(qml.Hermitian(np.eye(4), wires=[1, 2])), 2, "Var[H0]"),
            (qml.var(qml.NumberOperator(wires=[1])), 1, "Var[n]"),
            (qml.var(qml.X(wires=[1])), 1, "Var[x]"),
            (qml.var(qml.P(wires=[1])), 1, "Var[p]"),
            (
                qml.var(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])),
                1,
                "Var[|4,5,7X4,5,7|]",
            ),
            (
                qml.var(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1])),
                2,
                "Var[1+2x_0-1.3x_1+6p_1]",
            ),
            (
                qml.var(
                    qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5],
                                         [-1.3, 4.5, 2.3]]),
                               wires=[1])),
                1,
                "Var[1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0]",
            ),
            (qml.var(qml.QuadOperator(
                3.14, wires=[1])), 1, "Var[cos(3.14)x+sin(3.14)p]"),
            (qml.sample(qml.PauliX(wires=[1])), 1, "Sample[X]"),
            (qml.sample(qml.PauliY(wires=[1])), 1, "Sample[Y]"),
            (qml.sample(qml.PauliZ(wires=[1])), 1, "Sample[Z]"),
            (qml.sample(qml.Hadamard(wires=[1])), 1, "Sample[H]"),
            (qml.sample(qml.Hermitian(np.eye(4), wires=[1, 2
                                                        ])), 1, "Sample[H0]"),
            (qml.sample(qml.Hermitian(np.eye(4), wires=[1, 2
                                                        ])), 2, "Sample[H0]"),
            (qml.sample(qml.NumberOperator(wires=[1])), 1, "Sample[n]"),
            (qml.sample(qml.X(wires=[1])), 1, "Sample[x]"),
            (qml.sample(qml.P(wires=[1])), 1, "Sample[p]"),
            (
                qml.sample(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])),
                1,
                "Sample[|4,5,7X4,5,7|]",
            ),
            (
                qml.sample(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1
                                                                           ])),
                2,
                "Sample[1+2x_0-1.3x_1+6p_1]",
            ),
            (
                qml.sample(
                    qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5],
                                         [-1.3, 4.5, 2.3]]),
                               wires=[1])),
                1,
                "Sample[1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0]",
            ),
            (qml.sample(qml.QuadOperator(
                3.14, wires=[1])), 1, "Sample[cos(3.14)x+sin(3.14)p]"),
            (
                qml.expval(
                    qml.PauliX(wires=[1]) @ qml.PauliY(wires=[2])
                    @ qml.PauliZ(wires=[3])),
                1,
                "<X @ Y @ Z>",
            ),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])
                    @ qml.X(wires=[4])),
                1,
                "<|4,5,7X4,5,7| @ x>",
            ),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])
                    @ qml.X(wires=[4])),
                2,
                "<|4,5,7X4,5,7| @ x>",
            ),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])
                    @ qml.X(wires=[4])),
                3,
                "<|4,5,7X4,5,7| @ x>",
            ),
            (
                qml.expval(
                    qml.FockStateProjector(np.array([4, 5, 7]),
                                           wires=[1, 2, 3])
                    @ qml.X(wires=[4])),
                4,
                "<|4,5,7X4,5,7| @ x>",
            ),
            (
                qml.sample(
                    qml.Hermitian(np.eye(4), wires=[1, 2]) @ qml.Hermitian(
                        np.eye(4), wires=[0, 3])),
                0,
                "Sample[H0 @ H0]",
            ),
            (
                qml.sample(
                    qml.Hermitian(np.eye(4), wires=[1, 2]) @ qml.Hermitian(
                        2 * np.eye(4), wires=[0, 3])),
                0,
                "Sample[H0 @ H1]",
            ),
            (qml.probs([0]), 0, "Probs"),
            (state(), 0, "State"),
        ],
    )
    def test_output_representation_ascii(self, ascii_representation_resolver,
                                         obs, wire, target):
        """Test that an Observable instance with return type is properly resolved."""
        assert ascii_representation_resolver.output_representation(
            obs, wire) == target

    def test_element_representation_none(self,
                                         unicode_representation_resolver):
        """Test that element_representation properly handles None."""
        assert unicode_representation_resolver.element_representation(None,
                                                                      0) == ""

    def test_element_representation_str(self, unicode_representation_resolver):
        """Test that element_representation properly handles strings."""
        assert unicode_representation_resolver.element_representation(
            "Test", 0) == "Test"

    def test_element_representation_calls_output(
            self, unicode_representation_resolver):
        """Test that element_representation calls output_representation for returned observables."""

        unicode_representation_resolver.output_representation = Mock()

        obs = qml.sample(qml.PauliX(3))
        wire = 3

        unicode_representation_resolver.element_representation(obs, wire)

        assert unicode_representation_resolver.output_representation.call_args[
            0] == (obs, wire)

    def test_element_representation_calls_operator(
            self, unicode_representation_resolver):
        """Test that element_representation calls operator_representation for all operators that are not returned."""

        unicode_representation_resolver.operator_representation = Mock()

        op = qml.PauliX(3)
        wire = 3

        unicode_representation_resolver.element_representation(op, wire)

        assert unicode_representation_resolver.operator_representation.call_args[
            0] == (op, wire)
Пример #30
0
two_qubit = [
    (qml.CNOT(wires=[0, 1]), CNOT),
    (qml.SWAP(wires=[0, 1]), SWAP),
    (qml.CZ(wires=[0, 1]), CZ),
    (qml.CNOT(wires=[0, 1]).inv(), CNOT.conj().T),
    (qml.SWAP(wires=[0, 1]).inv(), SWAP.conj().T),
    (qml.CZ(wires=[0, 1]).inv(), CZ.conj().T),
]
# list of all parametrized two-qubit gates
two_qubit_param = [
    (qml.CRZ(0, wires=[0, 1]), crz),
    (qml.CRZ(0, wires=[0, 1]).inv(), lambda theta: crz(-theta)),
]
# list of all three-qubit gates
three_qubit = [
    (qml.Toffoli(wires=[0, 1, 2]), toffoli),
    (qml.CSWAP(wires=[0, 1, 2]), CSWAP),
    (qml.Toffoli(wires=[0, 1, 2]).inv(), toffoli.conj().T),
    (qml.CSWAP(wires=[0, 1, 2]).inv(), CSWAP.conj().T),
]


class TestStateApply:
    """Test the device's state after application of gates."""
    @pytest.mark.parametrize(
        "state",
        [
            np.array([0, 0, 1, 0]),
            np.array([0, 0, 1, 0]),
            np.array([1, 0, 1, 0]),
            np.array([1, 1, 1, 1]),