Repository: PennyLaneAI/pennylane

Issue #4350: [BUG] pennylane.numpy tensors become trainable multiplied by numpy.ndarray
Created: 2023-07-11T20:20:55Z
Expected behavior
The returned tensor should also have requires_grad=False
Actual behavior
The returned tensor has requires_grad=True
Additional information
This is troublesome because it happens in things like qml.transforms.one_qubit_decomposition. For example,
>>> U = qnp.array([[0, 1], [1, 0]], requires_grad=False)
>>> qml.QubitUnitary(U, 0).decomposition()
[RZ(tensor(1.57079633, requires_grad=True), wires=[0]),
 RY(tensor(3.14159265, requires_grad=True), wires=[0]),
 RZ(tensor(10.99557429, requires_grad=True), wires=[0])]
requires_grad is suddenly True in the results! This line in _convert_to_su2 is the culprit. The first term (the cast_like) still has requires_grad=False set, but once multiplied with the second term (the exp, a numpy.ndarray), the resulting value has requires_grad=True.
Note for fixer
We are not setting trainable parameters in validate_and_expand_adjoint (see #4365) partially because of this bug. While fixing this, consider adding it to that function and adjusting tests accordingly. Deciding what to do with tape.trainable_params is always messy, so I'll let you decide :)
Source code
from pennylane import numpy as qnp
import numpy as np
qnp.array(0.1, requires_grad=False) * np.array(0.2)
Tracebacks
No response
System information
pl dev
Existing GitHub issues

 I have searched existing GitHub issues to make sure the issue does not already exist.

Duplicate issue #1726: [BUG] `default.qubit.autograd` returns a tensor with `requires_grad=True`
Created: 2021-10-07T22:24:50Z
Expected behavior
The output of circuit execution is a tensor that has the requires_grad attribute set to True or False for all devices.
Most devices output a tensor with requires_grad=False:
import pennylane as qml
from pennylane.devices import DefaultQubit

dev = qml.device('lightning.qubit', wires=1)

@qml.qnode(dev)
def circuit():
    qml.PauliX(0)
    return qml.expval(qml.PauliX(0))
    
circuit()
tensor(0., requires_grad=False)

Actual behavior
The default.qubit.autograd device outputs a tensor with requires_grad=False:
import pennylane as qml
from pennylane.devices import DefaultQubit

dev = qml.device('default.qubit.autograd', wires=1)

@qml.qnode(dev)
def circuit():
    qml.PauliX(0)
    return qml.expval(qml.PauliX(0))
    
circuit()
tensor(0., requires_grad=True)

With a tape:
import pennylane as qml
from pennylane.devices import DefaultQubit

device = qml.device('default.qubit.autograd', wires=1)

with qml.tape.QuantumTape() as tape:
    qml.PauliX(0)
    qml.expval(qml.PauliX(0))
    
res = device.execute(tape)

print(res, type(res), res.requires_grad)
[0.] <class 'pennylane.numpy.tensor.tensor'> True

Having requires_grad=True for the output seems to be unified for all devices when using the beta QNode:
import pennylane as qml
from pennylane.devices import DefaultQubit

dev = qml.device('lightning.qubit', wires=1)

@qml.beta.qnode(dev)
def circuit():
    qml.PauliX(0)
    return qml.expval(qml.PauliX(0))
    
circuit()
tensor(0., requires_grad=True)

Additional information
The issue to tackle would be to have a standardized output. Switching to the beta QNode seems to solve this, however, I'm not sure if having requires_grad=True for all outputs was intentional behaviour. If so, then this issue can be simply closed. 🙂
Source code
No response
Tracebacks
No response
System information
Name: PennyLane
Version: 0.19.0.dev0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/XanaduAI/pennylane
Author: None
Author-email: None
License: Apache License 2.0
Location: /pennylane
Requires: numpy, scipy, networkx, autograd, toml, appdirs, semantic-version, autoray, cachetools, pennylane-lightning
Required-by: PennyLane-Cirq, PennyLane-Orquestra, PennyLane-SF, pennylane-qulacs, PennyLane-IonQ, amazon-braket-pennylane-plugin, PennyLane-Forest, PennyLane-Honeywell, PennyLane-qiskit, PennyLane-AQT, PennyLane-Lightning, PennyLane-Qchem
Platform info:           Linux-5.11.0-37-generic-x86_64-with-glibc2.10
Python version:          3.8.5
Numpy version:           1.20.3
Scipy version:           1.7.1
Installed devices:
- cirq.mixedsimulator (PennyLane-Cirq-0.17.1)
- cirq.pasqal (PennyLane-Cirq-0.17.1)
- cirq.qsim (PennyLane-Cirq-0.17.1)
- cirq.qsimh (PennyLane-Cirq-0.17.1)
- cirq.simulator (PennyLane-Cirq-0.17.1)
- orquestra.forest (PennyLane-Orquestra-0.15.0)
- orquestra.ibmq (PennyLane-Orquestra-0.15.0)
- orquestra.qiskit (PennyLane-Orquestra-0.15.0)
- orquestra.qulacs (PennyLane-Orquestra-0.15.0)
- strawberryfields.fock (PennyLane-SF-0.16.0.dev0)
- strawberryfields.gaussian (PennyLane-SF-0.16.0.dev0)
- strawberryfields.gbs (PennyLane-SF-0.16.0.dev0)
- strawberryfields.remote (PennyLane-SF-0.16.0.dev0)
- strawberryfields.tf (PennyLane-SF-0.16.0.dev0)
- qulacs.simulator (pennylane-qulacs-0.17.0.dev0)
- ionq.qpu (PennyLane-IonQ-0.17.0.dev0)
- ionq.simulator (PennyLane-IonQ-0.17.0.dev0)
- braket.aws.qubit (amazon-braket-pennylane-plugin-1.4.1.dev0)
- braket.local.qubit (amazon-braket-pennylane-plugin-1.4.1.dev0)
- forest.numpy_wavefunction (PennyLane-Forest-0.17.0.dev0)
- forest.qvm (PennyLane-Forest-0.17.0.dev0)
- forest.wavefunction (PennyLane-Forest-0.17.0.dev0)
- honeywell.hqs (PennyLane-Honeywell-0.16.0.dev0)
- qiskit.aer (PennyLane-qiskit-0.18.0.dev0)
- qiskit.basicaer (PennyLane-qiskit-0.18.0.dev0)
- qiskit.ibmq (PennyLane-qiskit-0.18.0.dev0)
- aqt.noisy_sim (PennyLane-AQT-0.18.0)
- aqt.sim (PennyLane-AQT-0.18.0)
- lightning.qubit (PennyLane-Lightning-0.19.0.dev0)
- default.gaussian (PennyLane-0.19.0.dev0)
- default.mixed (PennyLane-0.19.0.dev0)
- default.qubit (PennyLane-0.19.0.dev0)
- default.qubit.autograd (PennyLane-0.19.0.dev0)
- default.qubit.jax (PennyLane-0.19.0.dev0)
- default.qubit.tf (PennyLane-0.19.0.dev0)
- default.qubit.torch (PennyLane-0.19.0.dev0)
- default.tensor (PennyLane-0.19.0.dev0)
- default.tensor.tf (PennyLane-0.19.0.dev0)


### 

- [X] I have searched exisisting GitHub issues to make sure the issue does not already exist.

Closing comment (2023-07-11T20:22:36Z): I get the feeling this issue doesn't really apply anymore, but if it does, it might be related to #4350 ?