Closed antalszava closed 4 years ago
Good catch @antalszava! In the Operator
class, we do some basic input validation of arguments. However, this won't work for PassthruQNodes, since they will no longer be using NumPy arrays/Python floats, but rather the default data structure for their target ML framework.
In the PassthruQNode
, operation validation is turned off explicitly within the construct
method:
def _construct(self, args, kwargs):
"""Construct the quantum circuit graph by calling the quantum function.
Like :class:`.BaseQNode._construct`, but does not use Variables.
"""
# temporary queues for operations and observables
self.queue = [] #: list[Operation]: applied operations
self.obs_queue = [] #: list[Observable]: applied observables
# set up the context for Operator entry
with self:
try:
# turn off domain checking since PassthruQNode qfuncs can take any class as input
pennylane.operation.Operator.do_check_domain = False
# generate the program queue by executing the quantum circuit function
res = self.func(*args, **kwargs)
finally:
pennylane.operation.Operator.do_check_domain = True
My guess is that this seemingly doesn't propagate to decomposed operations, and it somehow gets turned on again?
I think I have found the cause. The operation decomposition is performed during the self._circuit_check
method call. So this just needs to be moved to within the try:
block:
# set up the context for Operator entry
with self:
try:
# turn off domain checking since PassthruQNode qfuncs can take any class as input
pennylane.operation.Operator.do_check_domain = False
# generate the program queue by executing the quantum circuit function
res = self.func(*args, **kwargs)
# check the validity of the circuit
self._check_circuit(res)
finally:
pennylane.operation.Operator.do_check_domain = True
del self.queue
del self.obs_queue
Applying this seems to result in another one for the same example:
~/pennylane/pennylane/_queuing_context.py in append_operator(cls, operator)
72 """
73 for context in cls._active_contexts:
---> 74 context._append_operator(operator) # pylint: disable=protected-access
75
76 @abc.abstractmethod
~/pennylane/pennylane/qnodes/base.py in _append_operator(self, operator)
329 if self.obs_queue:
330 raise QuantumFunctionError(
--> 331 "State preparations and gates must precede measured observables."
332 )
333 self.queue.append(operator)
QuantumFunctionError: State preparations and gates must precede measured observables.
This does not arise when using the decomposition explicitly.
Issue description
Expected behavior: Operations not supported by a device (e.g.
U3
givendefault.tensor.tf
) get decomposed well within aPassthruQNode
without any problems.Actual behavior: An error is raised due to a check that gets executed:
from pennylane.qnodes import PassthruQNode
theta = 0.543 phi = -0.234 lam = 0.654 p = [theta, phi, lam]
dev = qml.device("default.tensor.tf", wires=1)
def circuit(weights, w=None): qml.U3(weights[0], weights[1], weights[2], wires=w) # <--- decomposition is required return qml.expval(qml.PauliX(w))
node = PassthruQNode(circuit, dev, interface="tf")
params = tf.Variable(p, dtype=tf.float64)
with tf.GradientTape() as tape: tape.watch(params) res = node(params, w=0)
Reproduces how often: Each time a
PassthruQNode
is being used purely with TF using thedefault.tensor.tf
device.System information: (post the output of
import pennylane as qml; qml.about()
)microsoft.QuantumSimulator (PennyLane-qsharp-0.6.0)
cirq.simulator (PennyLane-Cirq-0.8.0)
forest.numpy_wavefunction (PennyLane-Forest-0.8.0)
forest.qpu (PennyLane-Forest-0.8.0)
forest.qvm (PennyLane-Forest-0.8.0)
forest.wavefunction (PennyLane-Forest-0.8.0)
qiskit.aer (PennyLane-qiskit-0.9.0.dev0)
qiskit.basicaer (PennyLane-qiskit-0.9.0.dev0)
qiskit.ibmq (PennyLane-qiskit-0.9.0.dev0)
projectq.classical (PennyLane-PQ-0.7.0.dev0)
projectq.ibm (PennyLane-PQ-0.7.0.dev0)
projectq.simulator (PennyLane-PQ-0.7.0.dev0)
default.gaussian (PennyLane-0.9.0.dev0)
default.qubit (PennyLane-0.9.0.dev0)
default.tensor (PennyLane-0.9.0.dev0)
default.tensor.tf (PennyLane-0.9.0.dev0)
strawberryfields.fock (PennyLane-SF-0.9.0.dev0)
strawberryfields.gaussian (PennyLane-SF-0.9.0.dev0)
Additional information
Testing of the
"classical"
differentiation method proposed in #552 will slightly change once this issue is resolved. This PR works with gate decomposition due to the error.