Exemplo n.º 1
0
    def test_non_differentiable(self):
        """Test that a non-differentiable parameter is
        correctly marked"""

        with qml.tape.JacobianTape() as tape:
            qml.FockState(1, wires=0)
            qml.Displacement(0.543, 0, wires=[1])
            qml.Beamsplitter(0, 0, wires=[0, 1])
            qml.expval(qml.X(wires=[0]))

        assert _grad_method(tape, 0) is None
        assert _grad_method(tape, 1) == "A"
        assert _grad_method(tape, 2) == "A"
        assert _grad_method(tape, 3) == "A"
        assert _grad_method(tape, 4) == "A"

        _gradient_analysis(tape)

        assert tape._par_info[0]["grad_method"] is None
        assert tape._par_info[1]["grad_method"] == "A"
        assert tape._par_info[2]["grad_method"] == "A"
        assert tape._par_info[3]["grad_method"] == "A"
        assert tape._par_info[4]["grad_method"] == "A"

        _gradient_analysis(tape)
Exemplo n.º 2
0
    def test_unknown_op_grad_method(self, monkeypatch):
        """Test that an exception is raised if an operator has a
        grad method defined that the CV parameter-shift tape
        doesn't recognize"""
        monkeypatch.setattr(qml.Rotation, "grad_method", "B")

        with qml.tape.JacobianTape() as tape:
            qml.Rotation(1.0, wires=0)
            qml.expval(qml.X(0))

        with pytest.raises(ValueError, match="unknown gradient method"):
            _grad_method(tape, 0)
Exemplo n.º 3
0
    def test_probability(self):
        """Probability is the expectation value of a
        higher order observable, and thus only supports numerical
        differentiation"""
        with qml.tape.JacobianTape() as tape:
            qml.Rotation(0.543, wires=[0])
            qml.Squeezing(0.543, 0, wires=[0])
            qml.probs(wires=0)

        assert _grad_method(tape, 0) == "F"
        assert _grad_method(tape, 1) == "F"
        assert _grad_method(tape, 2) == "F"
Exemplo n.º 4
0
    def test_finite_diff(self, monkeypatch):
        """If an op has grad_method=F, this should be respected
        by the qml.tape.JacobianTape"""
        monkeypatch.setattr(qml.Rotation, "grad_method", "F")

        with qml.tape.JacobianTape() as tape:
            qml.Rotation(0.543, wires=[0])
            qml.Squeezing(0.543, 0, wires=[0])
            qml.expval(qml.P(0))

        assert _grad_method(tape, 0) == "F"
        assert _grad_method(tape, 1) == "A"
        assert _grad_method(tape, 2) == "A"
Exemplo n.º 5
0
    def test_independent(self):
        """Test that an independent variable is properly marked
        as having a zero gradient"""

        with qml.tape.JacobianTape() as tape:
            qml.Rotation(0.543, wires=[0])
            qml.Rotation(-0.654, wires=[1])
            qml.expval(qml.P(0))

        assert _grad_method(tape, 0) == "A"
        assert _grad_method(tape, 1) == "0"

        _gradient_analysis(tape)

        assert tape._par_info[0]["grad_method"] == "A"
        assert tape._par_info[1]["grad_method"] == "0"
Exemplo n.º 6
0
    def test_second_order_expectation(self):
        """Test that the expectation of a second-order observable forces
        the gradient method to use the second-order parameter-shift rule"""

        with qml.tape.JacobianTape() as tape:
            qml.Rotation(1.0, wires=[0])
            qml.expval(qml.NumberOperator(0))  # second order

        assert _grad_method(tape, 0) == "A2"
Exemplo n.º 7
0
    def test_non_gaussian_operation(self):
        """Test that a non-Gaussian operation succeeding
        a differentiable Gaussian operation results in
        numeric differentiation."""

        with qml.tape.JacobianTape() as tape:
            qml.Rotation(1.0, wires=[0])
            qml.Rotation(1.0, wires=[1])
            # Non-Gaussian
            qml.Kerr(1.0, wires=[1])
            qml.expval(qml.P(0))
            qml.expval(qml.X(1))

        # First rotation gate has no succeeding non-Gaussian operation
        assert _grad_method(tape, 0) == "A"
        # Second rotation gate does no succeeding non-Gaussian operation
        assert _grad_method(tape, 1) == "F"
        # Kerr gate does not support the parameter-shift rule
        assert _grad_method(tape, 2) == "F"

        with qml.tape.JacobianTape() as tape:
            qml.Rotation(1.0, wires=[0])
            qml.Rotation(1.0, wires=[1])
            # entangle the modes
            qml.Beamsplitter(1.0, 0.0, wires=[0, 1])
            # Non-Gaussian
            qml.Kerr(1.0, wires=[1])
            qml.expval(qml.P(0))
            qml.expval(qml.X(1))

        # After entangling the modes, the Kerr gate now succeeds
        # both initial rotations
        assert _grad_method(tape, 0) == "F"
        assert _grad_method(tape, 1) == "F"
        assert _grad_method(tape, 2) == "F"
Exemplo n.º 8
0
    def test_variance(self):
        """If the variance of the observable is first order, then
        parameter-shift is supported. If the observable is second order,
        however, only finite-differences is supported."""

        with qml.tape.JacobianTape() as tape:
            qml.Rotation(1.0, wires=[0])
            qml.var(qml.P(0))  # first order

        assert _grad_method(tape, 0) == "A"

        with qml.tape.JacobianTape() as tape:
            qml.Rotation(1.0, wires=[0])
            qml.var(qml.NumberOperator(0))  # second order

        assert _grad_method(tape, 0) == "F"

        with qml.tape.JacobianTape() as tape:
            qml.Rotation(1.0, wires=[0])
            qml.Rotation(1.0, wires=[1])
            qml.Beamsplitter(0.5, 0.0, wires=[0, 1])
            qml.var(qml.NumberOperator(0))  # fourth order
            qml.expval(qml.NumberOperator(1))

        assert _grad_method(tape, 0) == "F"
        assert _grad_method(tape, 1) == "F"
        assert _grad_method(tape, 2) == "F"
        assert _grad_method(tape, 3) == "F"