def qfunc(a, b, c, d, e, f):
        qml.ThermalState(3, wires=[1])
        qml.GaussianState(2 * np.eye(8),
                          np.array([1, 1, 1, 2, 2, 3, 3, 3]),
                          wires=[0, 1, 2, 3])
        qml.Rotation(a, wires=0)
        qml.Rotation(b, wires=1)
        qml.Beamsplitter(d, 1, wires=[0, 1])
        qml.Beamsplitter(e, 1, wires=[1, 2])
        qml.Displacement(f, 0, wires=[3])
        qml.Squeezing(2.3, 0, wires=[0])
        qml.Squeezing(2.3, 0, wires=[2])
        qml.Beamsplitter(d, 1, wires=[1, 2])
        qml.Beamsplitter(e, 1, wires=[2, 3])
        qml.TwoModeSqueezing(2, 2, wires=[3, 1])
        qml.ControlledPhase(2.3, wires=[2, 1])
        qml.ControlledAddition(2, wires=[0, 3])
        qml.QuadraticPhase(4, wires=[0])

        return [
            qml.expval(qml.ops.PolyXP(np.array([0, 1, 2]), wires=0)),
            qml.expval(qml.ops.QuadOperator(4, wires=1)),
            qml.expval(
                qml.ops.FockStateProjector(np.array([1, 5]), wires=[2, 3])),
        ]
Beispiel #2
0
def parameterized_cv_tape():
    """A parametrized CV circuit."""
    a, b, c, d, e, f = 0.1, 0.2, 0.3, 47 / 17, 0.5, 0.6

    with qml.tape.QuantumTape() as tape:
        qml.ThermalState(3, wires=[1])
        qml.GaussianState(2 * np.eye(8),
                          np.array([1, 1, 1, 2, 2, 3, 3, 3]),
                          wires=[0, 1, 2, 3])
        qml.Rotation(a, wires=0)
        qml.Rotation(b, wires=1)
        qml.Beamsplitter(d, 1, wires=[0, 1])
        qml.Beamsplitter(e, 1, wires=[1, 2])
        qml.Displacement(f, 0, wires=[3])
        qml.Squeezing(2.3, 0, wires=[0])
        qml.Squeezing(2.3, 0, wires=[2])
        qml.Beamsplitter(d, 1, wires=[1, 2])
        qml.Beamsplitter(e, 1, wires=[2, 3])
        qml.TwoModeSqueezing(2, 2, wires=[3, 1])
        qml.ControlledPhase(2.3, wires=[2, 1])
        qml.ControlledAddition(2, wires=[0, 3])
        qml.QuadraticPhase(4, wires=[0])

        qml.expval(qml.ops.PolyXP(np.array([0, 1, 2]), wires=0))
        qml.expval(qml.ops.QuadOperator(4, wires=1))
        qml.expval(qml.ops.FockStateProjector(np.array([1, 5]), wires=[2, 3]))

    return tape
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)
Beispiel #4
0
 def circuit(*args):
     qml.Displacement(0.1, 0, wires=0)
     qml.TwoModeSqueezing(0.1, 0, wires=[0, 1])
     return qml.expval(op(*args, wires=wires))
Beispiel #5
0
 def circuit(*args):
     qml.TwoModeSqueezing(0.1, 0, wires=[0, 1])
     operation(*args, wires=wires)
     return qml.expval(qml.NumberOperator(0)), qml.expval(qml.NumberOperator(1))
Beispiel #6
0
 def circuit(*args):
     qml.TwoModeSqueezing(0.1, 0, wires=[0, 1])
     op(*args, wires=wires)
     return qml.expval.MeanPhoton(0), qml.expval.MeanPhoton(1)
class TestExpectationQuantumGradients:
    """Tests for the quantum gradients of various gates

    with expectation value output"""
    def test_rotation_gradient(self, mocker, tol):
        """Test the gradient of the rotation gate"""
        dev = qml.device("default.gaussian", wires=2, hbar=hbar)

        alpha = 0.5643
        theta = 0.23354

        with CVParamShiftTape() as tape:
            qml.Displacement(alpha, 0.0, wires=[0])
            qml.Rotation(theta, wires=[0])
            qml.expval(qml.X(0))

        tape._update_gradient_info()
        tape.trainable_params = {2}

        spy1 = mocker.spy(CVParamShiftTape, "parameter_shift_first_order")
        spy2 = mocker.spy(CVParamShiftTape, "parameter_shift_second_order")

        grad_A = tape.jacobian(dev, method="analytic")
        spy1.assert_called()
        spy2.assert_not_called()

        grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True)
        spy2.assert_called()

        expected = -hbar * alpha * np.sin(theta)
        assert np.allclose(grad_A, expected, atol=tol, rtol=0)
        assert np.allclose(grad_A2, expected, atol=tol, rtol=0)

    def test_beamsplitter_gradient(self, mocker, tol):
        """Test the gradient of the beamsplitter gate"""
        dev = qml.device("default.gaussian", wires=2, hbar=hbar)

        alpha = 0.5643
        theta = 0.23354

        with CVParamShiftTape() as tape:
            qml.Displacement(alpha, 0.0, wires=[0])
            qml.Beamsplitter(theta, 0.0, wires=[0, 1])
            qml.expval(qml.X(0))

        tape._update_gradient_info()
        tape.trainable_params = {2}

        spy1 = mocker.spy(CVParamShiftTape, "parameter_shift_first_order")
        spy2 = mocker.spy(CVParamShiftTape, "parameter_shift_second_order")

        grad_A = tape.jacobian(dev, method="analytic")
        spy1.assert_called()
        spy2.assert_not_called()

        grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True)
        spy2.assert_called()

        expected = -hbar * alpha * np.sin(theta)
        assert np.allclose(grad_A, expected, atol=tol, rtol=0)
        assert np.allclose(grad_A2, expected, atol=tol, rtol=0)

    def test_displacement_gradient(self, mocker, tol):
        """Test the gradient of the displacement gate"""
        dev = qml.device("default.gaussian", wires=2, hbar=hbar)

        r = 0.5643
        phi = 0.23354

        with CVParamShiftTape() as tape:
            qml.Displacement(r, phi, wires=[0])
            qml.expval(qml.X(0))

        tape._update_gradient_info()
        tape.trainable_params = {0, 1}

        spy1 = mocker.spy(CVParamShiftTape, "parameter_shift_first_order")
        spy2 = mocker.spy(CVParamShiftTape, "parameter_shift_second_order")

        grad_A = tape.jacobian(dev, method="analytic")
        spy1.assert_called()
        spy2.assert_not_called()

        grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True)
        spy2.assert_called()

        expected = [hbar * np.cos(phi), -hbar * r * np.sin(phi)]
        assert np.allclose(grad_A, expected, atol=tol, rtol=0)
        assert np.allclose(grad_A2, expected, atol=tol, rtol=0)

    def test_squeezed_gradient(self, mocker, tol):
        """Test the gradient of the squeezed gate. We also
        ensure that the gradient is correct even when an operation
        with no Heisenberg representation is a descendent."""
        dev = qml.device("default.gaussian", wires=2, hbar=hbar)

        class Rotation(qml.operation.CVOperation):
            """Dummy operation that does not support
            heisenberg representation"""

            num_wires = 1
            num_params = 1
            grad_method = "A"

        alpha = 0.5643
        r = 0.23354

        with CVParamShiftTape() as tape:
            qml.Displacement(alpha, 0.0, wires=[0])
            qml.Squeezing(r, 0.0, wires=[0])

            # The following two gates have no effect
            # on the circuit gradient and expectation value
            qml.Beamsplitter(0.0, 0.0, wires=[0, 1])
            Rotation(0.543, wires=[1])

            qml.expval(qml.X(0))

        tape._update_gradient_info()
        tape.trainable_params = {2}

        spy1 = mocker.spy(CVParamShiftTape, "parameter_shift_first_order")
        spy2 = mocker.spy(CVParamShiftTape, "parameter_shift_second_order")

        grad_A = tape.jacobian(dev, method="analytic")
        spy1.assert_called()
        spy2.assert_not_called()

        grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True)
        spy2.assert_called()

        expected = -np.exp(-r) * hbar * alpha
        assert np.allclose(grad_A, expected, atol=tol, rtol=0)
        assert np.allclose(grad_A2, expected, atol=tol, rtol=0)

    def test_squeezed_number_state_gradient(self, mocker, tol):
        """Test the numerical gradient of the squeeze gate with
        with number state expectation is correct"""
        dev = qml.device("default.gaussian", wires=2, hbar=hbar)

        r = 0.23354

        with CVParamShiftTape() as tape:
            qml.Squeezing(r, 0.0, wires=[0])
            # the fock state projector is a 'non-Gaussian' observable
            qml.expval(qml.FockStateProjector(np.array([2, 0]), wires=[0, 1]))

        tape._update_gradient_info()
        tape.trainable_params = {0}
        assert tape._par_info[0]["grad_method"] == "F"

        spy = mocker.spy(CVParamShiftTape, "parameter_shift")
        grad = tape.jacobian(dev)
        spy.assert_not_called()

        # (d/dr) |<2|S(r)>|^2 = 0.5 tanh(r)^3 (2 csch(r)^2 - 1) sech(r)
        expected = 0.5 * np.tanh(r)**3 * (2 / (np.sinh(r)**2) - 1) / np.cosh(r)
        assert np.allclose(grad, expected, atol=tol, rtol=0)

    def test_multiple_squeezing_gradient(self, mocker, tol):
        """Test that the gradient of a circuit with two squeeze
        gates is correct."""
        dev = qml.device("default.gaussian", wires=2, hbar=hbar)

        r0, phi0, r1, phi1 = [0.4, -0.3, -0.7, 0.2]

        with CVParamShiftTape() as tape:
            qml.Squeezing(r0, phi0, wires=[0])
            qml.Squeezing(r1, phi1, wires=[0])
            qml.expval(qml.NumberOperator(0))  # second order

        tape._update_gradient_info()

        spy2 = mocker.spy(CVParamShiftTape, "parameter_shift_second_order")
        grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True)
        spy2.assert_called()

        # check against the known analytic formula
        expected = np.zeros([4])
        expected[0] = np.cosh(2 * r1) * np.sinh(
            2 * r0) + np.cos(phi0 - phi1) * np.cosh(2 * r0) * np.sinh(2 * r1)
        expected[1] = -0.5 * np.sin(phi0 - phi1) * np.sinh(2 * r0) * np.sinh(
            2 * r1)
        expected[2] = np.cos(phi0 - phi1) * np.cosh(2 * r1) * np.sinh(
            2 * r0) + np.cosh(2 * r0) * np.sinh(2 * r1)
        expected[3] = 0.5 * np.sin(phi0 - phi1) * np.sinh(2 * r0) * np.sinh(
            2 * r1)

        assert np.allclose(grad_A2, expected, atol=tol, rtol=0)

    def test_multiple_second_order_observables(self, mocker, tol):
        """Test that the gradient of a circuit with multiple
        second order observables is correct"""

        dev = qml.device("default.gaussian", wires=2, hbar=hbar)
        r = [0.4, -0.7, 0.1, 0.2]
        p = [0.1, 0.2, 0.3, 0.4]

        with CVParamShiftTape() as tape:
            qml.Squeezing(r[0], p[0], wires=[0])
            qml.Squeezing(r[1], p[1], wires=[0])
            qml.Squeezing(r[2], p[2], wires=[1])
            qml.Squeezing(r[3], p[3], wires=[1])
            qml.expval(qml.NumberOperator(0))  # second order
            qml.expval(qml.NumberOperator(1))  # second order

        tape._update_gradient_info()

        spy2 = mocker.spy(CVParamShiftTape, "parameter_shift_second_order")
        grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True)
        spy2.assert_called()

        # check against the known analytic formula

        def expected_grad(r, p):
            return np.array([
                np.cosh(2 * r[1]) * np.sinh(2 * r[0]) +
                np.cos(p[0] - p[1]) * np.cosh(2 * r[0]) * np.sinh(2 * r[1]),
                -0.5 * np.sin(p[0] - p[1]) * np.sinh(2 * r[0]) *
                np.sinh(2 * r[1]),
                np.cos(p[0] - p[1]) * np.cosh(2 * r[1]) * np.sinh(2 * r[0]) +
                np.cosh(2 * r[0]) * np.sinh(2 * r[1]),
                0.5 * np.sin(p[0] - p[1]) * np.sinh(2 * r[0]) *
                np.sinh(2 * r[1]),
            ])

        expected = np.zeros([2, 8])
        expected[0, :4] = expected_grad(r[:2], p[:2])
        expected[1, 4:] = expected_grad(r[2:], p[2:])

        assert np.allclose(grad_A2, expected, atol=tol, rtol=0)

    @pytest.mark.parametrize("obs", [qml.X, qml.Identity])
    @pytest.mark.parametrize("op", [
        qml.Displacement(0.1, 0.2, wires=0),
        qml.TwoModeSqueezing(0.1, 0.2, wires=[0, 1])
    ])
    def test_gradients_gaussian_circuit(self, op, obs, mocker, tol):
        """Tests that the gradients of circuits of gaussian gates match between the
        finite difference and analytic methods."""
        tol = 1e-2

        with CVParamShiftTape() as tape:
            qml.Displacement(0.5, 0, wires=0)
            qml.apply(op)
            qml.Beamsplitter(1.3, -2.3, wires=[0, 1])
            qml.Displacement(-0.5, 0.1, wires=0)
            qml.Squeezing(0.5, -1.5, wires=0)
            qml.Rotation(-1.1, wires=0)
            qml.expval(obs(wires=0))

        dev = qml.device("default.gaussian", wires=2)
        res = tape.execute(dev)

        tape._update_gradient_info()
        tape.trainable_params = set(range(2, 2 + op.num_params))

        # check that every parameter is analytic
        for i in range(op.num_params):
            assert tape._par_info[2 + i]["grad_method"][0] == "A"

        spy = mocker.spy(CVParamShiftTape, "parameter_shift_first_order")
        grad_F = tape.jacobian(dev, method="numeric")
        grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True)

        spy.assert_not_called()
        assert np.allclose(grad_A2, grad_F, atol=tol, rtol=0)

        if obs.ev_order == 1:
            grad_A = tape.jacobian(dev, method="analytic")
            spy.assert_called()
            assert np.allclose(grad_A, grad_F, atol=tol, rtol=0)

    @pytest.mark.parametrize("t", [0, 1])
    def test_interferometer_unitary(self, t, tol):
        """An integration test for CV gates that support analytic differentiation
        if succeeding the gate to be differentiated, but cannot be differentiated
        themselves (for example, they may be Gaussian but accept no parameters,
        or may accept a numerical array parameter.).

        This ensures that, assuming their _heisenberg_rep is defined, the quantum
        gradient analytic method can still be used, and returns the correct result.

        Currently, the only such operation is qml.InterferometerUnitary. In the future,
        we may consider adding a qml.GaussianTransfom operator.
        """

        if t == 1:
            pytest.xfail(
                "There is a bug in the second order CV parameter-shift rule; "
                "phase arguments return the incorrect derivative.")

            # Note: this bug currently affects PL core as well:
            #
            # dev = qml.device("default.gaussian", wires=2)
            #
            # U = np.array([[ 0.51310276+0.81702166j,  0.13649626+0.22487759j],
            #         [ 0.26300233+0.00556194j, -0.96414101-0.03508489j]])
            #
            # @qml.qnode(dev)
            # def circuit(r, phi):
            #     qml.Displacement(r, phi, wires=0)
            #     qml.InterferometerUnitary(U, wires=[0, 1])
            #     return qml.expval(qml.X(0))

            #
            # r = 0.543
            # phi = 0.
            #
            # >>> print(circuit.jacobian([r, phi], options={"force_order2":False}))
            # [[ 1.02620552 0.14823494]]
            # >>> print(circuit.jacobian([r, phi], options={"force_order2":True}))
            # [[ 1.02620552 -0.88728552]]

        U = np.array([
            [0.51310276 + 0.81702166j, 0.13649626 + 0.22487759j],
            [0.26300233 + 0.00556194j, -0.96414101 - 0.03508489j],
        ])

        with CVParamShiftTape() as tape:
            qml.Displacement(0.543, 0, wires=0)
            qml.InterferometerUnitary(U, wires=[0, 1])
            qml.expval(qml.X(0))

        tape._update_gradient_info()
        tape.trainable_params = {t}
        assert tape._par_info[0]["grad_method"] == "A"
        assert tape._par_info[1]["grad_method"] == "A"

        dev = qml.device("default.gaussian", wires=2)
        grad_F = tape.jacobian(dev, method="numeric")
        grad_A = tape.jacobian(dev, method="analytic")
        grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True)

        # the different methods agree
        assert np.allclose(grad_A, grad_F, atol=tol, rtol=0)
        assert np.allclose(grad_A2, grad_F, atol=tol, rtol=0)
Beispiel #8
0
 def circuit(r, phi, input_state, output_state):
     qml.FockStateVector(input_state, wires=[0, 1])
     qml.TwoModeSqueezing(r, phi, wires=[0, 1])
     return qml.expval(
         qml.FockStateProjector(output_state, wires=[0, 1]))
Beispiel #9
0
 def circuit(weights, input_state=None, **kwargs):
     qml.FockStateVector(input_state, wires=[0, 1])
     qml.TwoModeSqueezing(weights[0], weights[1], wires=[0, 1])
Beispiel #10
0
 def circuit(*x):
     qml.Displacement(0.1, 0, wires=0)
     qml.TwoModeSqueezing(0.1, 0, wires=[0, 1])
     return op(*x, wires=wires)