Interferometer compatibility with sf device

I am trying to use the Interferometer gate in a qnode running on the strawberry fields.fock device but I’m getting an error “Gate Interferometer not supported on device strawberryfields.fock”

Interferometer is within the module and is supposed to be compatible. Any ideas why this will never work or is there a clever workaround. I’m really interested in implementing an arbitrary unitary with trainable elements and Interferometer seemed the most elegant way.

Hi @Benjamin_Gregory! That is odd, as far as I can tell the Interferometer gate should work with strawberryfields.fock.

Do you have a minimal (non)-working code example you could share?

import tensorflow as tf
import pennylane as qml
from pennylane import numpy as np
import as sf

#import tensorflow.contrib.eager as tfe

M = int(5)  #modenumber
K = int(M*(M-1)/2)
allmodes =list(range(M))

GBS_dev = qml.device("strawberryfields.fock", wires= M, cutoff_dim=10)

theta = np.random.uniform(0, 2*np.pi, K)
phi = np.random.uniform(0, 2*np.pi, K)
input_squeeze = .4*np.pi

#define device, squeezing first and then interferometer
def device(theta, input_squeeze):
    qml.Squeezing(1, input_squeeze, wires = 1)
    qml.Interferometer(theta, wires = [0,1])
     return qml.expval(qml.NumberOperator(0))

device(theta, input_squeeze)

Hi @Benjamin_Gregory, I had a look through your code, and you’re right, qml.Interferometer is currently not working with strawberryfields.fock. I’ll make a pull request on GitHub to fix that.

However, to train an arbitrary interferometer, you probably don’t want this operation. Note that we have two similar operations:

  • qml.Interferometer(U, wires): accepts a numeric unitary matrix, determining a fixed interferometer.

  • qml.templates.layers.Interferometer(theta, phi, varphi, wires): accepts an array of parameters theta, phi, and varphi, and creates a mesh of beamsplitters and rotation gates for applying a parametrized unitary.

In this case, it is probably the latter function you want. Check out the documentation for more details on this function and its arguments.

Here is a quick example using the Interferometer layer template:

import numpy as np
import pennylane as qml
from pennylane.templates.layers import Interferometer
from pennylane.init import interferometer_uniform

import tensorflow as tf
import tensorflow.contrib.eager as tfe

M = 5

GBS_dev = qml.device("strawberryfields.gaussian", wires=M)

@qml.qnode(GBS_dev, interface="tf")
def device(params, input_squeeze):
    # get beamsplitter angles
    theta = params[:M*(M-1)//2]
    # get beamsplitter phases
    phi = params[M*(M-1)//2:2*M*(M-1)//2]
    # get local rotations
    varphi = params[-M:]

    for w in range(M):
        qml.Squeezing(1, input_squeeze, wires=w)

    Interferometer(theta, phi, varphi, wires=range(M))

    return [qml.expval(qml.NumberOperator(i)) for i in range(M)]

input_squeeze = 0.4*np.pi
params = tfe.Variable(np.concatenate(interferometer_uniform(M)))

print(device(params, input_squeeze))

Hi @josh
thanks for your help

I am having two problems with your suggestion

  1. NumberOperator not supported with sf.gaussian or sf.fock device
  2. tf.Variable object is not iterable

also is there a reason you switched to sf.gaussian over sf.fock device?