# Copyright 2018-2021 Xanadu Quantum Technologies Inc.# Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at# http://www.apache.org/licenses/LICENSE-2.0# Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License."""This module contains the :class:`OperationRecorder`."""# pylint: disable=too-many-argumentsfrompennylane.queuingimportAnnotatedQueue,QueuingManager,process_queuefrom.tapeimportQuantumScript
[docs]classOperationRecorder(QuantumScript,AnnotatedQueue):"""A template and quantum function inspector, allowing easy introspection of operators that have been applied without requiring a QNode. **Example**: The OperationRecorder is a context manager. Executing templates or quantum functions stores applied operators in the recorder, which can then be printed. >>> shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=1, n_wires=2) >>> weights = np.random.random(shape) >>> >>> with OperationRecorder() as rec: >>> qml.templates.StronglyEntanglingLayers(weights, wires=[0, 1]) Alternatively, the :attr:`~.OperationRecorder.queue` attribute can be used to directly access the applied :class:`~.Operation` and :class:`~.Observable` objects. """def__init__(self,ops=None,measurements=None,shots=None,):# pylint: disable=unused-argument, too-many-argumentsAnnotatedQueue.__init__(self)QuantumScript.__init__(self,ops,measurements,shots)self.ops=Noneself.obs=Nonedef__enter__(self):returnAnnotatedQueue.__enter__(self)def__exit__(self,exception_type,exception_value,traceback):AnnotatedQueue.__exit__(self,exception_type,exception_value,traceback)# After other optimizations in #2963, #2986 and follow-up work, we should check whether# calling `_process_queue` only if there is no `exception_type` saves time. This would# be done via the following:# if exception_type is None:# self._process_queue()self._ops,self._measurements=process_queue(self)self._update()forobj,infoinself.items():QueuingManager.append(obj,**info)new_tape=self.expand(depth=5,stop_at=lambdaobj:notisinstance(obj,QuantumScript))self.ops=new_tape.operationsself.obs=new_tape.observablesdef__str__(self):return"\n".join(["Operations","==========",*[repr(op)foropinself.ops],"","Observables","===========",*[repr(op)foropinself.obs],"",])@propertydefqueue(self):returnself.ops+self.obsdef__getitem__(self,key):""" Overrides the default because OperationRecorder is both a QuantumScript and an AnnotatedQueue. If key is an int, the caller is likely indexing the backing QuantumScript. Otherwise, the caller is likely indexing the backing AnnotatedQueue. """ifisinstance(key,int):returnQuantumScript.__getitem__(self,key)returnAnnotatedQueue.__getitem__(self,key)def__setitem__(self,key,val):AnnotatedQueue.__setitem__(self,key,val)