Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
Turns off QNode caching by default and makes variable values available during construction #209
Currently, the way the QNode works uses a method of 'JIT' circuit compilation:
From this point on, the user's function is never called again --- the QNode has cached all the information about the arguments, operations, and expectations to directly query the device.
However, there is a potential (advanced) use case where the user might want to do classical processing on keyword arguments within the QNode. This is generally a safe procedure, as QNodes, by default, treat keyword arguments as non-differentiable data.
Description of the Change:
To allow the above code pattern, the following has been modified:
This PR makes the following code pattern legal:
@qml.qnode(dev) def circuit(x, c=None): qml.RX(x, wires=0) for i in range(c): qml.RX(x, wires=i) return qml.expval.PauliZ(0) circuit(0.5, c=2)
i.e., you can perform classical processing of keyword arguments inside the QNode --- data that is assumed to be non-differentiable, and programmatically change the circuit structure.
Related GitHub Issues: https://discuss.pennylane.ai/t/passing-non-differentiable-arguments-to-qnode/135/14
@@ Coverage Diff @@ ## master #209 +/- ## ===================================== Coverage 100% 100% ===================================== Files 30 30 Lines 1851 1878 +27 ===================================== + Hits 1851 1878 +27
Needs to express that turning on this experimental option changes PennyLane from only evaluating the users quantum function once -> evaluating it on every QNode call.
Good point. It might not... perhaps I can perform the 'variable unpacking' in the construct method, and pass the direct values to the users quantum function. This would be a one line change --- I'll explore this tomorrow and see if this works/make sure it doesn't break anything.
I've added the following:
if self.cache: # caching mode, must use variables for kwargs # so they can be updated without reconstructing res = self.func(*variables, **kwarg_variables) else: # no caching, fine to directly pass kwarg values res = self.func(*variables, **keyword_values)
This works really nicely, removes the need to use