Beispiel #1
0
    def test_su2su2_to_tensor_products(self, U_pair):
        """Test SU(2) x SU(2) can be correctly factored into tensor products."""
        true_matrix = qml.math.kron(np.array(U_pair[0]), np.array(U_pair[1]))

        A, B = _su2su2_to_tensor_products(true_matrix)

        assert check_matrix_equivalence(qml.math.kron(A, B), true_matrix)
Beispiel #2
0
    def test_convert_to_su4(self, U):
        """Test a matrix in U(4) is correct converted to SU(4)."""
        U_su4 = _convert_to_su4(np.array(U))

        # Ensure the determinant is correct and the mats are equivalent up to a phase
        assert qml.math.isclose(qml.math.linalg.det(U_su4), 1.0)
        assert check_matrix_equivalence(np.array(U), U_su4)
Beispiel #3
0
    def test_zyz_decomposition_jax(self, U, expected_gate, expected_params):
        """Test that a one-qubit operation in JAX is correctly decomposed."""
        jax = pytest.importorskip("jax")

        # Enable float64 support
        from jax.config import config

        remember = config.read("jax_enable_x64")
        config.update("jax_enable_x64", True)

        U = jax.numpy.array(U, dtype=jax.numpy.complex128)

        obtained_gates = zyz_decomposition(U, wire="a")

        assert len(obtained_gates) == 1
        assert isinstance(obtained_gates[0], expected_gate)
        assert obtained_gates[0].wires == Wires("a")

        assert qml.math.allclose(qml.math.unwrap(obtained_gates[0].parameters),
                                 expected_params)

        if obtained_gates[0].num_params == 1:
            obtained_mat = qml.RZ(obtained_gates[0].parameters[0],
                                  wires=0).matrix
        else:
            obtained_mat = qml.Rot(*obtained_gates[0].parameters,
                                   wires=0).matrix

        assert check_matrix_equivalence(obtained_mat, U)
    def test_zyz_decomposition_tf(self, U, expected_gate, expected_params):
        """Test that a one-qubit operation in Tensorflow is correctly decomposed."""
        tf = pytest.importorskip("tensorflow")

        U = tf.Variable(U, dtype=tf.complex128)

        obtained_gates = zyz_decomposition(U, wire="a")

        assert len(obtained_gates) == 1
        assert isinstance(obtained_gates[0], expected_gate)
        assert obtained_gates[0].wires == Wires("a")
        assert qml.math.allclose(qml.math.unwrap(obtained_gates[0].parameters),
                                 expected_params)

        print(qml.math.unwrap(obtained_gates[0].parameters))
        print(expected_params)

        if obtained_gates[0].num_params == 1:
            # With TF and RZ, need to cast since can't just unwrap
            obtained_mat = qml.RZ(obtained_gates[0].parameters[0].numpy(),
                                  wires=0).matrix
        else:
            obtained_mat = qml.Rot(*qml.math.unwrap(
                obtained_gates[0].parameters),
                                   wires=0).matrix

        assert check_matrix_equivalence(obtained_mat, U)
Beispiel #5
0
    def test_two_qubit_decomposition_tf(self, U, wires):
        """Test that a two-qubit operation in Tensorflow is correctly decomposed."""
        tf = pytest.importorskip("tensorflow")

        U = tf.Variable(U, dtype=tf.complex128)

        obtained_decomposition = two_qubit_decomposition(U, wires=wires)

        with qml.tape.QuantumTape() as tape:
            for op in obtained_decomposition:
                qml.apply(op)

        obtained_matrix = get_unitary_matrix(tape, wire_order=wires)()

        assert check_matrix_equivalence(U, obtained_matrix, atol=1e-7)
Beispiel #6
0
    def test_two_qubit_decomposition_1_cnot(self, U, wires):
        """Test that a two-qubit matrix using one CNOT is correctly decomposed."""
        U = _convert_to_su4(np.array(U))

        assert _compute_num_cnots(U) == 1

        obtained_decomposition = two_qubit_decomposition(U, wires=wires)
        assert len(obtained_decomposition) == 5

        with qml.tape.QuantumTape() as tape:
            for op in obtained_decomposition:
                qml.apply(op)

        obtained_matrix = get_unitary_matrix(tape, wire_order=wires)()

        assert check_matrix_equivalence(U, obtained_matrix, atol=1e-7)
Beispiel #7
0
    def test_two_qubit_decomposition_tensor_products(self, U_pair, wires):
        """Test that a two-qubit tensor product matrix is correctly decomposed."""
        U = _convert_to_su4(
            qml.math.kron(np.array(U_pair[0]), np.array(U_pair[1])))

        assert _compute_num_cnots(U) == 0

        obtained_decomposition = two_qubit_decomposition(U, wires=wires)
        assert len(obtained_decomposition) == 2

        with qml.tape.QuantumTape() as tape:
            for op in obtained_decomposition:
                qml.apply(op)

        obtained_matrix = get_unitary_matrix(tape, wire_order=wires)()

        assert check_matrix_equivalence(U, obtained_matrix, atol=1e-7)
Beispiel #8
0
    def test_zyz_decomposition(self, U, expected_gate, expected_params):
        """Test that a one-qubit matrix in isolation is correctly decomposed."""
        obtained_gates = zyz_decomposition(U, Wires("a"))

        assert len(obtained_gates) == 1
        assert isinstance(obtained_gates[0], expected_gate)
        assert obtained_gates[0].wires == Wires("a")
        assert qml.math.allclose(obtained_gates[0].parameters, expected_params)

        if obtained_gates[0].num_params == 1:
            obtained_mat = qml.RZ(obtained_gates[0].parameters[0],
                                  wires=0).matrix
        else:
            obtained_mat = qml.Rot(*obtained_gates[0].parameters,
                                   wires=0).matrix

        assert check_matrix_equivalence(obtained_mat, U)
Beispiel #9
0
    def test_two_qubit_decomposition_tensor_products_torch(
            self, U_pair, wires):
        """Test that a two-qubit tensor product in Torch is correctly decomposed."""
        torch = pytest.importorskip("torch")

        U1 = torch.tensor(U_pair[0], dtype=torch.complex128)
        U2 = torch.tensor(U_pair[1], dtype=torch.complex128)
        U = qml.math.kron(U1, U2)

        obtained_decomposition = two_qubit_decomposition(U, wires=wires)

        with qml.tape.QuantumTape() as tape:
            for op in obtained_decomposition:
                qml.apply(op)

        obtained_matrix = get_unitary_matrix(tape, wire_order=wires)()

        assert check_matrix_equivalence(U, obtained_matrix, atol=1e-7)
Beispiel #10
0
    def test_two_qubit_decomposition_3_cnots(self, U, wires):
        """Test that a two-qubit matrix using 3 CNOTs is correctly decomposed."""
        U = _convert_to_su4(np.array(U))

        assert _compute_num_cnots(U) == 3

        obtained_decomposition = two_qubit_decomposition(U, wires=wires)
        assert len(obtained_decomposition) == 10

        with qml.tape.QuantumTape() as tape:
            for op in obtained_decomposition:
                qml.apply(op)

        obtained_matrix = get_unitary_matrix(tape, wire_order=wires)()

        # We check with a slightly great tolerance threshold here simply because the
        # test matrices were copied in here with reduced precision.
        assert check_matrix_equivalence(U, obtained_matrix, atol=1e-7)
def test_unitary_to_rot_multiple_two_qubit(num_reps):
    """Test that numerous two-qubit unitaries can be decomposed sequentially."""

    dev = qml.device("default.qubit", wires=2)

    U = np.array(test_two_qubit_unitaries[1], dtype=np.complex128)

    def my_circuit():
        for rep in range(num_reps):
            qml.QubitUnitary(U, wires=[0, 1])
        return qml.expval(qml.PauliZ(0))

    original_qnode = qml.QNode(my_circuit, dev)
    transformed_qnode = qml.QNode(unitary_to_rot(my_circuit), dev)

    original_matrix = qml.transforms.get_unitary_matrix(original_qnode)()
    transformed_matrix = qml.transforms.get_unitary_matrix(transformed_qnode)()

    assert check_matrix_equivalence(original_matrix, transformed_matrix, atol=1e-7)
Beispiel #12
0
    def test_two_qubit_decomposition_jax(self, U, wires):
        """Test that a two-qubit operation in JAX is correctly decomposed."""
        jax = pytest.importorskip("jax")

        from jax.config import config

        remember = config.read("jax_enable_x64")
        config.update("jax_enable_x64", True)

        U = jax.numpy.array(U, dtype=jax.numpy.complex128)

        obtained_decomposition = two_qubit_decomposition(U, wires=wires)

        with qml.tape.QuantumTape() as tape:
            for op in obtained_decomposition:
                qml.apply(op)

        obtained_matrix = get_unitary_matrix(tape, wire_order=wires)()

        assert check_matrix_equivalence(U, obtained_matrix, atol=1e-7)
Beispiel #13
0
    def test_zyz_decomposition_torch(self, U, expected_gate, expected_params):
        """Test that a one-qubit operation in Torch is correctly decomposed."""
        torch = pytest.importorskip("torch")

        U = torch.tensor(U, dtype=torch.complex128)

        obtained_gates = zyz_decomposition(U, wire="a")

        assert len(obtained_gates) == 1
        assert isinstance(obtained_gates[0], expected_gate)
        assert obtained_gates[0].wires == Wires("a")
        assert qml.math.allclose(qml.math.unwrap(obtained_gates[0].parameters),
                                 expected_params)

        if obtained_gates[0].num_params == 1:
            obtained_mat = qml.RZ(obtained_gates[0].parameters[0],
                                  wires=0).matrix
        else:
            obtained_mat = qml.Rot(*obtained_gates[0].parameters,
                                   wires=0).matrix

        assert check_matrix_equivalence(obtained_mat, qml.math.unwrap(U))