Conditional gate implementation

I’m curious if I can design a circuit in which I apply a gate on a qumode based on the outcome of a measurement on another qumode, something like this:

device = qml.device('strawberryfields.fock', cutoff_dim=5, wires=2)

@qml.qnode(device, interface='torch')
def circ(x, theta, phi):
    qml.Displacement(4.0, x, wires=[0])
    qml.Displacement(4.0, x, wires=[1])
    qml.Beamsplitter(theta, phi, wires=[0,1])
    qml.Squeezing( qml.expval(qml.P(0)), np.pi, wires=[1] )
    return qml.expval(qml.X(1))

x = torch.tensor(.0991, requires_grad=True)
theta = torch.tensor(.744, requires_grad=True)
phi = torch.tensor(.655, requires_grad=True)

circ(x, theta, phi)

When running the code above, I get an error:

TypeError: Squeezing: Real scalar parameter expected, got <class 'pennylane.ops.cv.P'>.

Hey @dnnagy,

This behaviour is currently not supported in PennyLane.

It’s something we could think about implementing in the future. However, it is not clear that it plays well with the automatic differentiation which is the core feature of the library (because you can’t usually compute a gradient of a conditioning step), so depending on your use-case, it may or may not be of value to have this in the library.

In the meantime, this is supported in our sister library, Strawberry Fields:

import strawberryfields as sf
from strawberryfields import ops

prog = sf.Program(2)

x = .0991
theta = .744
phi = .655

with prog.context as q:
    ops.Dgate(4.0, x)          | q[0]
    ops.Dgate(4.0, x)          | q[1]
    ops.BSgate(theta, phi)     | q
    MeasureP                   | q[0]
    ops.Sgate(q[0].par, np.pi) | q[1]
    MeasureX                   | q[1]

eng = sf.Engine("gaussian", backend_options={"cutoff_dim": 5})
results = eng.run(prog)

Check out the Strawberry Fields teleportation tutorial for more details on photonic feed-forward.

1 Like