Thank you for the responses. Unfortunately I couldn’t make it work with the new version.
With the old version of pennylane (0.29) it works, exactly like doing
return [qml.expval(qml.PauliZ(i)) for i in range(self.n_qubits)]
but with the new one (0.36) I get this error:
Traceback (most recent call last):
File "/Users/vini/Documents/phd/test_pennylane/test.py", line 72, in <module>
test_circuit()
File "/Users/vini/Documents/phd/test_pennylane/test.py", line 64, in test_circuit
sample = generator(noise)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
return forward_call(*args, **kwargs)
File "/Users/vini/Documents/phd/test_pennylane/test.py", line 48, in forward
expsZ = self.quantum_circuit(batch, self.q_params)
File "/Users/vini/Documents/phd/test_pennylane/test.py", line 42, in quantum_circuit
return qnode(noise, weights)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/pennylane/workflow/qnode.py", line 1098, in __call__
res = self._execution_component(args, kwargs, override_shots=override_shots)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/pennylane/workflow/qnode.py", line 1073, in _execution_component
return _to_qfunc_output_type(
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/pennylane/workflow/qnode.py", line 101, in _to_qfunc_output_type
return type(qfunc_output)(results)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/pennylane/numpy/tensor.py", line 111, in __new__
obj = asarray(input_array, *args, **kwargs)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/autograd/tracer.py", line 48, in f_wrapped
return f_raw(*args, **kwargs)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/pennylane/numpy/tensor.py", line 36, in asarray
return _np.array(vals, *args, **kwargs)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/autograd/numpy/numpy_wrapper.py", line 58, in array
return array_from_args(args, kwargs, *map(array, A))
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/autograd/numpy/numpy_wrapper.py", line 60, in array
return _array_from_scalar_or_array(args, kwargs, A)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/autograd/tracer.py", line 48, in f_wrapped
return f_raw(*args, **kwargs)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/autograd/numpy/numpy_wrapper.py", line 73, in _array_from_scalar_or_array
return _np.array(scalar, *array_args, **array_kwargs)
File "/Users/vini/miniforge3/envs/qml/lib/python3.9/site-packages/torch/_tensor.py", line 970, in __array__
return self.numpy()
RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.
In both cases I have
numpy==1.22
torch==2.0
autograd==1.5
I made a minimal version of my code that reproduces the same error:
import pennylane as qml
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import sys
class Generator(nn.Module):
def __init__(self, qubits, layers):
super().__init__()
self.n_qubits = qubits
self.number_param_layers = layers
self.q_params = nn.Parameter(torch.rand(2 * self.number_param_layers * self.n_qubits), requires_grad = True)
def circ(self, noise, weights):
weights = weights.reshape(self.number_param_layers, self.n_qubits, 2)
# encoding
for j in range(self.n_qubits):
qml.RX(noise[j], wires = j)
# repeated layer
for i in range(self.number_param_layers):
# parameterised
for j in range(self.n_qubits):
qml.RY(weights[i][j][0], wires = j)
qml.RZ(weights[i][j][1], wires = j)
# control-z gates
for j in range(self.n_qubits - 1):
qml.CZ(wires = [j, j + 1])
#return [qml.expval(qml.PauliZ(i)) for i in range(self.n_qubits)]
return qml.math.stack([qml.expval(qml.PauliZ(i)) for i in range(self.n_qubits)])
def quantum_circuit(self, noise, weights):
dev = qml.device('lightning.qubit', wires = self.n_qubits, shots = None)
qnode = qml.QNode(self.circ, dev, interface = 'torch', diff_method = 'parameter-shift')
return qnode(noise, weights)
def forward(self, x):
sample = torch.zeros((x.shape[0], self.n_qubits)).to(torch.float32)
for b, batch in enumerate(x):
expsZ = self.quantum_circuit(batch, self.q_params)
sample[b,:] = expsZ
return sample
def test_circuit():
n_qubits = int(sys.argv[1])
layers = 1
generator = Generator(n_qubits, layers)
opt = optim.SGD(generator.parameters(), 0.03)
batch_size = 16
trainset = torch.rand((1_000, n_qubits))
dataloader = torch.utils.data.DataLoader(trainset, batch_size = batch_size, drop_last = True)
for iteration, data in enumerate(dataloader):
print(f'Generator parameters at step {iteration}: {generator.q_params}')
noise = torch.rand((batch_size, n_qubits))
sample = generator(noise)
loss = (sample - data).sum()
generator.zero_grad()
loss.backward()
opt.step()
if __name__ == '__main__':
test_circuit()