import numpy as np import pennylane as qml import torch.nn as nn def encode(n_qubits, inputs): for wire in range(n_qubits): qml.RX(inputs[wire], wires=wire) def layer(n_qubits, y_weight, z_weight): for wire, y_weight in enumerate(y_weight): qml.RY(y_weight, wires=wire) for wire, z_weight in enumerate(z_weight): qml.RZ(z_weight, wires=wire) for wire in range(n_qubits): qml.CZ(wires=[wire, (wire + 1) % n_qubits]) def measure(n_qubits): return [qml.expval(qml.PauliZ(wire)) for wire in range(n_qubits)] def get_model(n_qubits, n_layers, data_reupload): # NOTE: need to select an appropriate device # dev = qml.device('lightning.gpu', wires=n_qubits) dev = qml.device("default.qubit", wires=n_qubits) shapes = { "y_weights": (n_layers, n_qubits), "z_weights": (n_layers, n_qubits) } @qml.qnode(dev, interface='torch') def circuit(inputs, y_weights, z_weights): for layer_idx in range(n_layers): if (layer_idx == 0) or data_reupload: encode(n_qubits, inputs) layer(n_qubits, y_weights[layer_idx], z_weights[layer_idx]) return measure(n_qubits) model = qml.qnn.TorchLayer(circuit, shapes) return model class QuantumNet(nn.Module): def __init__(self, n_layers): super(QuantumNet, self).__init__() self.n_qubits = 4 self.n_actions = 4 self.q_layers = get_model(n_qubits=self.n_qubits, n_layers=n_layers, data_reupload=False) def forward(self, inputs): inputs = inputs * np.pi outputs = self.q_layers(inputs) outputs = (1 + outputs) / 2 return outputs