# How to do encoding in QNN efficiently in strawberryfields so that Optimizers can work easily in variational setting

**URL:** <https://discuss.pennylane.ai/t/how-to-do-encoding-in-qnn-efficiently-in-strawberryfields-so-that-optimizers-can-work-easily-in-variational-setting/3257>\
**Category:** Strawberry Fields\
**Created:** [August 1, 2023, 11:51am UTC](https://discuss.pennylane.ai/t/how-to-do-encoding-in-qnn-efficiently-in-strawberryfields-so-that-optimizers-can-work-easily-in-variational-setting/3257 "2023-08-01T11:51:33Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Prabhat\_Kumar](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/prabhat_kumar/32/1435_2.png) [@Prabhat\_Kumar](https://discuss.pennylane.ai/u/Prabhat_Kumar)\
**Post date:** [August 1, 2023, 11:51am UTC](https://discuss.pennylane.ai/t/how-to-do-encoding-in-qnn-efficiently-in-strawberryfields-so-that-optimizers-can-work-easily-in-variational-setting/3257/1 "2023-08-01T11:51:33Z")

</div>

I am working on a toy problem of regression using QNN circuit given in strawberry fields’ website. There, we have used tensorflow’s apply\_gradient method, that follows your parameter in the forward pass (from 10th line to 7th).

```auto
for i in range(1000):
    # reset the engine if it has already been executed
    if eng.run_progs:
        eng.reset()

    with tf.GradientTape() as tape:
        loss, fid, ket, trace = cost(weights)

    # one repetition of the optimization
    gradients = tape.gradient(loss, weights)
    opt.apply_gradients(zip([gradients], [weights]))

```

where cost function is

```auto
def cost(weights):
    # Create a dictionary mapping from the names of the Strawberry Fields
    # symbolic gate parameters to the TensorFlow weight values.
    mapping = {p.name: w for p, w in zip(sf_params.flatten(), tf.reshape(weights, [-1]))}

    # run the engine
    state = eng.run(qnn, args=mapping).state
    ket = state.ket()

    difference = tf.reduce_sum(tf.abs(ket - target_state))
    fidelity = tf.abs(tf.reduce_sum(tf.math.conj(ket) * target_state)) ** 2
    return difference, fidelity, ket, tf.math.real(state.trace())

```

We can see that weights are given in the circuit as arg in eng.run(). This works well and good until I have to add X values (regression AX=Y) as parameters to the circuit. But I don’t want the gradients with respect to those X values.

I have done the following for encoding of X values into the circuit

```auto
with qnn.context as q:
  for i in range(N):
    ops.Dgate(x[0][i],0) | q[i] # this is where I am encoding.

  for k in range(layers):
      layer(sf_params[k], q)

```

and a little tweaking in the cost function as follows

```auto

def cost(param): # X_target should be scalar and X 1-D

  #mapping = {p.name: w for p, w in zip(sf_params.flatten(), tf.reshape(params[i], [-1]))}

  a=np.concatenate([sf_params.flatten(),x.flatten()])
  b=tf.convert_to_tensor(np.concatenate([np.reshape(param, [-1]),X[0]]))
  mapping = {p.name: w for p, w in zip(a,b)}

 # all of this is just to include x values in mapping.
  pred = eng.run(qnn, args=mapping).state
  Y = pred.quad_expectation(0,phi=0.)[0]
  diff = tf.abs(tf.cast(Y,dtype=tf.float64)-y[0])

  return diff

```

and main looks like

```auto
opt = tf.keras.optimizers.Adam(learning_rate = lr)

cost_progress = []
best_fid = 0

# same old thing

eng = sf.Engine(backend='tf',backend_options={"cutoff_dim":cutoff})
qnn = sf.Program(N)

sf_params = np.arange(num_params).reshape(params.shape).astype(str)
sf_params = np.array([qnn.params(*i) for i in sf_params])

# a mere modification
x= np.arange(num_params,N+num_params).astype(str)
x= np.array([qnn.params(*i) for i in [x]])
y = tf.constant(y)
X = tf.constant(X)

with qnn.context as q:
  for i in range(N):
    ops.Dgate(x[0][i],0) | q[i]

  for k in range(layers):
      layer(sf_params[k], q)

  #ops.MeasureX | q[0],q[1]

cost_progress=[]
for i in range(reps):
  

  if eng.run_progs:
    eng.reset()

  with tf.GradientTape() as tape:
    tape.watch(params)
    loss = cost(params)
        

  # one repetition of the optimization
  gradients = tape.gradient(loss, params)
  print(i, loss ,params, gradients)
  opt.apply_gradients(zip([gradients], [params]))

  cost_progress.append(loss)

```

This code is unable to calculate the gradients, it gives gradients= NONE, when I print them. And I think, it is only due to the above complexity of the code. So, what is the efficient way to do all this, so that my optimizer can understand my cost function.

Exact error is the following  
ValueError: No gradients provided for any variable: ([‘Variable:0’],). Provided `grads_and_vars` is ((None, \<tf.Variable ‘Variable:0’ shape=(1, 14) dtype=float32, numpy=  
array([[ 1.6708091e-02, 2.2838793e-05, -5.2734390e-03, -6.9317231e-03,  
-3.0103172e-03, 3.6114827e-03, -1.0168127e-02, 6.7833858e-03,  
1.1122092e-02, 1.8201470e-02, -8.2193566e-03, -6.1826045e-03,  
1.2012760e-02, 1.0526734e-02]], dtype=float32)\>),).

---

<div class="post-metadata">

**Author:** ![Prabhat\_Kumar](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/prabhat_kumar/32/1435_2.png) [@Prabhat\_Kumar](https://discuss.pennylane.ai/u/Prabhat_Kumar)\
**Post date:** [August 2, 2023, 2:30pm UTC](https://discuss.pennylane.ai/t/how-to-do-encoding-in-qnn-efficiently-in-strawberryfields-so-that-optimizers-can-work-easily-in-variational-setting/3257/2 "2023-08-02T14:30:20Z")

</div>

I guess since I have got the problem solved, I’ll put it here. I don’t understand the significance of the current syntax of using mapping instead of good old pennylane format, that is why I still prefer a better and efficient way to use quantum circuits.  
But the whole problem was not from strawberryfields’ front. It was a problem from tensorflow front that I broke the graph by using convert\_to\_tensor in the cost function. All I did was to start all my variables as tensors and use tf function solely and it worked. For example, params and x were made tf.Variable and tf.concat helped me to join them both in cost function.

---

<div class="post-metadata">

**Author:** ![isaacdevlugt](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/isaacdevlugt/32/1159_2.png) [@isaacdevlugt](https://discuss.pennylane.ai/u/isaacdevlugt)\
**Post date:** [August 2, 2023, 2:42pm UTC](https://discuss.pennylane.ai/t/how-to-do-encoding-in-qnn-efficiently-in-strawberryfields-so-that-optimizers-can-work-easily-in-variational-setting/3257/3 "2023-08-02T14:42:42Z")

</div>

Hey @Prabhat_Kumar! Welcome back to the forum 😁

I was in the middle of writing back to you but you responded with a solution!

> It was a problem from tensorflow front that I broke the graph by using convert\_to\_tensor in the cost function

This is a good point in that whenever you’re doing machine learning, it’s best practice to always stay within the data types of the machine learning language you are using. In this case, using TF-native functions to manipulate tensors to your liking is the way to do it, as jumping in and out of TF via NumPy can be problematic in some cases.

I’m glad you found a solution though! If you don’t mind, can you share the full code example just for anyone looking at this thread in the future?
