Strawberryfields tensorflow cannot convert to EagerTensor

Hi.
Using strawberryfields.tf and transforming the qnodes into keras layers, when trying to train a network that has some gates that are controlled by the inputs I get the error: Cannot convert 1.5707963267948966 to EagerTensor of dtype int32

Below a version of the code I created to pinpoint the problem:

dev = qml.device('strawberryfields.tf', wires=4, cutoff_dim=3)

def layer(theta, phi, wires):
    M = len(wires)
    phi_nonlinear = np.pi / 2

    qml.templates.Interferometer(
        theta, phi, np.zeros(M), wires=wires, mesh="rectangular",
    )

    for i in wires:
        qml.Kerr(phi_nonlinear, wires=i)

@qml.qnode(dev)
def quantum_neural_net(inputs, var):
    wires = list(range(len(inputs)-1))
    activ = inputs[len(inputs)-1]
    

    # Encode input x into a sequence of quantum fock states
    for i in wires:
        qml.FockState(inputs[i], wires=i)

    qml.ops.cv.Beamsplitter(activ*(np.pi/2), (np.pi/2), wires = [0, 1])
    
    
    # "layer" subcircuits
    for i, v in enumerate(var):
        layer(v[: len(v) // 2], v[len(v) // 2 :], wires)
     
    return [qml.expval(qml.NumberOperator(w)) for w in wires]

X = np.array([[1, 0, 1, 0, 0],
          [1, 0, 1, 0, 1]], requires_grad=False)

Y = np.array([[1, 0, 1, 0],
          [0, 1, 0, 1]], requires_grad=False)

num_layers = 4
M = len(X[0])-1
num_variables_per_layer = M * (M - 1)

weight_shapes = {"var": (num_layers, num_variables_per_layer)}
qlayer = qml.qnn.KerasLayer(quantum_neural_net, weight_shapes, output_dim=6)
model = tf.keras.models.Sequential([qlayer])
LR_ST = 0.1
opt = tf.keras.optimizers.Adam(learning_rate = LR_ST)
model.compile(opt, loss="mae", metrics=["accuracy"])

fitting = model.fit(X, Y, epochs=10, verbose=2)

The problem seems to be generated by the line:
qml.ops.cv.Beamsplitter(activ*(np.pi/2), (np.pi/2), wires = [0, 1])

Where “activ” is one of the inputs passed which is either 0 or 1 and deactivates/activates the gate.
This code was working fine on pennylane 0.13 with pennylane-sf 0.12, but on pennylane 0.15.1 with pennylane-sf 0.15 it gives the error:

Epoch 1/10
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-2f1fafb4ef74> in <module>
----> 1 fitting = model.fit(X, Y, epochs=10, verbose=2)

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)
   1181                 _r=1):
   1182               callbacks.on_train_batch_begin(step)
-> 1183               tmp_logs = self.train_function(iterator)
   1184               if data_handler.should_sync:
   1185                 context.async_wait()

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\training.py in train_function(iterator)
    853       def train_function(iterator):
    854         """Runs a training execution with one step."""
--> 855         return step_function(self, iterator)
    856 
    857     else:

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\training.py in step_function(model, iterator)
    843 
    844       data = next(iterator)
--> 845       outputs = model.distribute_strategy.run(run_step, args=(data,))
    846       outputs = reduce_per_replica(
    847           outputs, self.distribute_strategy, reduction='first')

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\distribute\distribute_lib.py in run(***failed resolving arguments***)
   1283       fn = autograph.tf_convert(
   1284           fn, autograph_ctx.control_status_ctx(), convert_by_default=False)
-> 1285       return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
   1286 
   1287   def reduce(self, reduce_op, value, axis):

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\distribute\distribute_lib.py in call_for_each_replica(self, fn, args, kwargs)
   2831       kwargs = {}
   2832     with self._container_strategy().scope():
-> 2833       return self._call_for_each_replica(fn, args, kwargs)
   2834 
   2835   def _call_for_each_replica(self, fn, args, kwargs):

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\distribute\distribute_lib.py in _call_for_each_replica(self, fn, args, kwargs)
   3606   def _call_for_each_replica(self, fn, args, kwargs):
   3607     with ReplicaContext(self._container_strategy(), replica_id_in_sync_group=0):
-> 3608       return fn(*args, **kwargs)
   3609 
   3610   def _reduce_to(self, reduce_op, value, destinations, options):

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\autograph\impl\api.py in wrapper(*args, **kwargs)
    595   def wrapper(*args, **kwargs):
    596     with ag_ctx.ControlStatusCtx(status=ag_ctx.Status.UNSPECIFIED):
--> 597       return func(*args, **kwargs)
    598 
    599   if inspect.isfunction(func) or inspect.ismethod(func):

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\training.py in run_step(data)
    836 
    837       def run_step(data):
--> 838         outputs = model.train_step(data)
    839         # Ensure counter is updated only if `train_step` succeeds.
    840         with ops.control_dependencies(_minimum_control_deps(outputs)):

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\training.py in train_step(self, data)
    793     # Run forward pass.
    794     with backprop.GradientTape() as tape:
--> 795       y_pred = self(x, training=True)
    796       loss = self.compiled_loss(
    797           y, y_pred, sample_weight, regularization_losses=self.losses)

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\base_layer.py in __call__(self, *args, **kwargs)
   1028         with autocast_variable.enable_auto_cast_variables(
   1029             self._compute_dtype_object):
-> 1030           outputs = call_fn(inputs, *args, **kwargs)
   1031 
   1032         if self._activity_regularizer:

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\sequential.py in call(self, inputs, training, mask)
    378       if not self.built:
    379         self._init_graph_network(self.inputs, self.outputs)
--> 380       return super(Sequential, self).call(inputs, training=training, mask=mask)
    381 
    382     outputs = inputs  # handle the corner case where self.layers is empty

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\functional.py in call(self, inputs, training, mask)
    419     """
    420     return self._run_internal_graph(
--> 421         inputs, training=training, mask=mask)
    422 
    423   def compute_output_shape(self, input_shape):

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\functional.py in _run_internal_graph(self, inputs, training, mask)
    554 
    555         args, kwargs = node.map_arguments(tensor_dict)
--> 556         outputs = node.layer(*args, **kwargs)
    557 
    558         # Update tensor_dict.

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\keras\engine\base_layer.py in __call__(self, *args, **kwargs)
   1028         with autocast_variable.enable_auto_cast_variables(
   1029             self._compute_dtype_object):
-> 1030           outputs = call_fn(inputs, *args, **kwargs)
   1031 
   1032         if self._activity_regularizer:

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\pennylane\qnn\keras.py in call(self, inputs)
    285             reconstructor = []
    286             for x in tf.unstack(inputs):
--> 287                 reconstructor.append(self.call(x))
    288             return tf.stack(reconstructor)
    289 

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\pennylane\qnn\keras.py in call(self, inputs)
    288             return tf.stack(reconstructor)
    289 
--> 290         return self._evaluate_qnode(inputs)
    291 
    292     def _evaluate_qnode(self, x):

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\pennylane\qnn\keras.py in _evaluate_qnode(self, x)
    300         """
    301         kwargs = {**{self.input_arg: x}, **{k: 1.0 * w for k, w in self.qnode_weights.items()}}
--> 302         return self.qnode(**kwargs)
    303 
    304     def compute_output_shape(self, input_shape):

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\pennylane\qnode.py in __call__(self, *args, **kwargs)
    550         if self.mutable or self.qtape is None:
    551             # construct the tape
--> 552             self.construct(args, kwargs)
    553 
    554         # execute the tape

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\pennylane\qnode.py in construct(self, args, kwargs)
    479 
    480         with self.qtape:
--> 481             self.qfunc_output = self.func(*args, **kwargs)
    482 
    483         if not isinstance(self.qfunc_output, Sequence):

<ipython-input-3-2535adc305fa> in quantum_neural_net(inputs, var)
      9         qml.FockState(inputs[i], wires=i)
     10 
---> 11     qml.ops.cv.Beamsplitter(activ*(np.pi/2), (np.pi/2), wires = [0, 1])
     12 
     13 

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\ops\math_ops.py in binary_op_wrapper(x, y)
   1248             return out
   1249           except (TypeError, ValueError):
-> 1250             raise e
   1251         else:
   1252           raise

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\ops\math_ops.py in binary_op_wrapper(x, y)
   1232         #   r_binary_op_wrapper use different force_same_dtype values.
   1233         x, y = maybe_promote_tensors(x, y, force_same_dtype=False)
-> 1234         return func(x, y, name=name)
   1235       except (TypeError, ValueError) as e:
   1236         # Even if dispatching the op failed, the RHS may be a tensor aware

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\ops\math_ops.py in _mul_dispatch(x, y, name)
   1573     return sparse_tensor.SparseTensor(y.indices, new_vals, y.dense_shape)
   1574   else:
-> 1575     return multiply(x, y, name=name)
   1576 
   1577 

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\util\dispatch.py in wrapper(*args, **kwargs)
    204     """Call target, and fall back on dispatchers if there is a TypeError."""
    205     try:
--> 206       return target(*args, **kwargs)
    207     except (TypeError, ValueError):
    208       # Note: convert_to_eager_tensor currently raises a ValueError, not a

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\ops\math_ops.py in multiply(x, y, name)
    528   """
    529 
--> 530   return gen_math_ops.mul(x, y, name)
    531 
    532 

C:\ProgramData\Anaconda3\envs\Pennylane14TF\lib\site-packages\tensorflow\python\ops\gen_math_ops.py in mul(x, y, name)
   6234     try:
   6235       _result = pywrap_tfe.TFE_Py_FastPathExecute(
-> 6236         _ctx, "Mul", name, x, y)
   6237       return _result
   6238     except _core._NotOkStatusException as e:

TypeError: Cannot convert 1.5707963267948966 to EagerTensor of dtype int32

Does anyone know how to avoid this issue?

Hi @Denis-Stanev!

The issue might be that your X and Y tensors are of type tf.int32, which results (further down the line) in activ also being of type tf.int32. Unfortunately TensorFlow requires multiplied tensors to all be of the same type, so there are two potential solutions:

  1. Change X and Y to tf.float64 tensors
  2. Cast activ to tf.float64 before performing the multiplication.

As to why this used to work in PL 0.13 – perhaps the older version of PennyLane was automatically casting the input tensors to tf.float64, so this was happening implicitly under the hood?

1 Like

Your solution has solved the problem.
Thank you very much for your help.