# Hybrid quantum optics neural network

**URL:** https://discuss.pennylane.ai/t/hybrid-quantum-optics-neural-network/984
**Category:** PennyLane Help
**Created:** [April 19, 2021, 1:25pm UTC](https://discuss.pennylane.ai/t/hybrid-quantum-optics-neural-network/984 "2021-04-19T13:25:43Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Hamitonian](https://avatars.discourse-cdn.com/v4/letter/h/e495f1/32.png) [@Hamitonian](https://discuss.pennylane.ai/u/Hamitonian)
#### Post date: [April 19, 2021, 1:25pm UTC](https://discuss.pennylane.ai/t/hybrid-quantum-optics-neural-network/984/1 "2021-04-19T13:25:43Z")

</div>

When I tried to hybrid quantum optics neural network with classical one, the Error raised, it says that: _QuantumFunctionError: Continuous and discrete operations are not allowed in the same quantum circuit._  
But I don’t know why, could you please help me modify this incorrect code? My previous codes are as follows:

```
import tensorflow as tf
import pennylane as qml

import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_moons

# Set random seeds
np.random.seed(42)
tf.random.set_seed(42)

X, y = make_moons(n_samples=200, noise=0.1)
y_hot = tf.keras.utils.to_categorical(y, num_classes=2) # one-hot encoded labels

c = ["#1f77b4" if y_ == 0 else "#ff7f0e" for y_ in y] # colours for each class
plt.axis("off")
plt.scatter(X[:, 0], X[:, 1], c=c)
plt.show()

tf.keras.backend.set_floatx('float64')

layer_1 = tf.keras.layers.Dense(2, activation="relu")
layer_2 = tf.keras.layers.Dense(2, activation="softmax")

model = tf.keras.Sequential([layer_1, layer_2])
model.compile(loss="mae")

n_qubits = 2
n_layers = 6
dev = qml.device("default.qubit", wires=n_qubits)

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", beamsplitter="pennylane"
    )

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

@qml.qnode(dev)
def quantum_neural_net(inputs, weights):
    wires = list(range(len(inputs)))

    # Encode input x into a sequence of quantum fock states
    qml.templates.AngleEmbedding(inputs, wires=range(n_qubits))

    # "layer" subcircuits
    for i, v in enumerate(weights):
        layer(v[: len(v) // 2], v[len(v) // 2 :], wires)

    return [qml.expval(qml.PauliZ(wires=i)) for i in range(n_qubits)]

M = 2
num_variables_per_layer = M * (M - 1)
weight_shapes = {"weights": (n_layers, num_variables_per_layer)}
qlayer = qml.qnn.KerasLayer(quantum_neural_net, weight_shapes, output_dim=n_qubits)

clayer_1 = tf.keras.layers.Dense(2)
clayer_2 = tf.keras.layers.Dense(2, activation="softmax")
model = tf.keras.models.Sequential([clayer_1, qlayer, clayer_2])

opt = tf.keras.optimizers.SGD(learning_rate=0.2)
model.compile(opt, loss="mae", metrics=["accuracy"])

fitting = model.fit(X, y_hot, epochs=6, batch_size=5, validation_split=0.25, verbose=2)
```

---

<div class="post-metadata">

### Author: ![glassnotes](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/glassnotes/32/327_2.png) [@glassnotes](https://discuss.pennylane.ai/u/glassnotes)
#### Post date: [April 19, 2021, 9:53pm UTC](https://discuss.pennylane.ai/t/hybrid-quantum-optics-neural-network/984/2 "2021-04-19T21:53:01Z")

</div>

Hi @Hamitonian,

The error is occuring because the continuous variable (CV) operations like `qml.Kerr` are not supported on the device because it is a qubit device, rather than a qumode device. To perform such gates, you’ll have to use a different type of device that supports CV operations (such as `strawberryfields.fock`).

Note that on those devices, however, it will then no longer be possible to use a template like `AngleEmbedding`, since this is an operation on qubits. So I think you’ll need two devices and a bit of re-writing to get the code working with both types of operations.

There’s an example in [this demo](https://pennylane.ai/qml/demos/tutorial_plugins_hybrid.html#hybrid-computation) that might be helpful here. It shows a hybrid network that combines the output of one QNode that runs on a qubit device, and another that runs on a CV device.

Hope that helps, please let us know if you have any further questions!

---

<div class="post-metadata">

### Author: ![Hamitonian](https://avatars.discourse-cdn.com/v4/letter/h/e495f1/32.png) [@Hamitonian](https://discuss.pennylane.ai/u/Hamitonian)
#### Post date: [April 20, 2021, 4:59pm UTC](https://discuss.pennylane.ai/t/hybrid-quantum-optics-neural-network/984/3 "2021-04-20T16:59:11Z")

</div>

Thanks for your generous help!  
I’ve changed my code but suffered another problem, it says that _Beamsplitter: Real scalar parameter expected, got \<class ‘numpy.ndarray’\>._, but I have no idea how to solve this problem, here is my code:

```
import tensorflow as tf
import pennylane as qml
from pennylane import numpy as np
tf.keras.backend.set_floatx('float64')
from sklearn.datasets import make_moons

layer_1 = tf.keras.layers.Dense(2)
layer_2 = tf.keras.layers.Dense(2, activation="softmax")

model = tf.keras.Sequential([layer_1, layer_2])
model.compile(loss="mae")

# Set random seeds
np.random.seed(42)
tf.random.set_seed(42)

X, y = make_moons(n_samples=200, noise=0.1)
y_hot = tf.keras.utils.to_categorical(y, num_classes=2) # one-hot encoded labels

n_qubits = 2
dev = qml.device("strawberryfields.fock", wires=2, cutoff_dim=4)

@qml.qnode(dev)
def qnode(inputs, weights):
    qml.Displacement(inputs[0], 0, wires=0)
    qml.Displacement(inputs[1], 0, wires=1)
    qml.Beamsplitter(weights[0], weights[1], wires=[0, 1])
    qml.Rotation(weights[2], 0, wires=0)
    qml.Rotation(weights[3], 0, wires=1)
    return [qml.expval(qml.NumberOperator(wires=i)) for i in range(n_qubits)]

n_layers = 6
weight_shapes = {"weights": (n_layers, 4, 1)}

qlayer = qml.qnn.KerasLayer(qnode, weight_shapes, output_dim=n_qubits)

clayer_1 = tf.keras.layers.Dense(2)
clayer_2 = tf.keras.layers.Dense(2, activation="softmax")
model = tf.keras.models.Sequential([clayer_1, qlayer, clayer_2])
opt = tf.keras.optimizers.SGD(learning_rate=0.2)
model.compile(opt, loss="mae", metrics=["accuracy"])
fitting = model.fit(X, y_hot, epochs=6, batch_size=5, validation_split=0.25, verbose=2)

```

**Another question** is that how to restrict the weights in my Qnode to [-2_pi, 2_pi], in consideration of phaseshift and beamsplitter.

---

<div class="post-metadata">

### Author: ![Hamitonian](https://avatars.discourse-cdn.com/v4/letter/h/e495f1/32.png) [@Hamitonian](https://discuss.pennylane.ai/u/Hamitonian)
#### Post date: [April 20, 2021, 5:01pm UTC](https://discuss.pennylane.ai/t/hybrid-quantum-optics-neural-network/984/4 "2021-04-20T17:01:17Z")

</div>

I follow the example given by [https://pennylane.ai/qml/demos/tutorial\_qnn\_module\_tf.html](https://pennylane.ai/qml/demos/tutorial_qnn_module_tf.html)

---

<div class="post-metadata">

### Author: ![glassnotes](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/glassnotes/32/327_2.png) [@glassnotes](https://discuss.pennylane.ai/u/glassnotes)
#### Post date: [April 20, 2021, 9:00pm UTC](https://discuss.pennylane.ai/t/hybrid-quantum-optics-neural-network/984/5 "2021-04-20T21:00:01Z")

</div>

Hi @Hamiltonian,

The error with the beamsplitter is because of the shape of the `weights` vector being used - it has shape `(6, 4, 1)`, so calling `weights[0]` will give a vector of shape `(4, 1)` rather than a single value (which is what’s expected). You’ll have to modify the shape of `weights`, or adjust the QNode to extract the desired entries.

Additional constraints on the weights can be added when initializing the `KerasLayer` through the `weight_specs` argument (see the “Usage Details” section of the [docs](https://pennylane.readthedocs.io/en/stable/code/api/pennylane.qnn.KerasLayer.html) for an example). I think the example there with [`tf.keras.initializers.RandomUniform`](https://www.tensorflow.org/api_docs/python/tf/random_uniform_initializer) is the one you’ll want, as it allows specification of bounds on the values.

---

<div class="post-metadata">

### Author: ![Amandeep](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/amandeep/32/385_2.png) [@Amandeep](https://discuss.pennylane.ai/u/Amandeep)
#### Post date: [May 31, 2023, 3:18pm UTC](https://discuss.pennylane.ai/t/hybrid-quantum-optics-neural-network/984/6 "2023-05-31T15:18:20Z")

</div>

@Hamitonian  
hi,

I am working on this hybrid model with quantum optical nn. Can you please is it working on your side?

---

<div class="post-metadata">

### Author: ![Amandeep](https://yyz2.discourse-cdn.com/flex012/user_avatar/discuss.pennylane.ai/amandeep/32/385_2.png) [@Amandeep](https://discuss.pennylane.ai/u/Amandeep)
#### Post date: [May 31, 2023, 3:19pm UTC](https://discuss.pennylane.ai/t/hybrid-quantum-optics-neural-network/984/7 "2023-05-31T15:19:44Z")

</div>

@glassnotes  
Hi, I worked on the same problem. But the issue is that loss is converging and accuracy remains constant. Can you please help…
