# 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 qml.expval measurement."""fromcollections.abcimportSequencefromtypingimportOptional,Unionimportpennylaneasqmlfrompennylane.operationimportOperatorfrompennylane.wiresimportWiresfrom.measurementsimportExpectation,SampleMeasurement,StateMeasurementfrom.mid_measureimportMeasurementValuefrom.sampleimportSampleMP
[docs]defexpval(op:Union[Operator,MeasurementValue],):r"""Expectation value of the supplied observable. **Example:** .. code-block:: python3 dev = qml.device("default.qubit", wires=2) @qml.qnode(dev) def circuit(x): qml.RX(x, wires=0) qml.Hadamard(wires=1) qml.CNOT(wires=[0, 1]) return qml.expval(qml.Y(0)) Executing this QNode: >>> circuit(0.5) -0.4794255386042029 Args: op (Union[Observable, MeasurementValue]): a quantum observable object. To get expectation values for mid-circuit measurements, ``op`` should be a ``MeasurementValue``. Returns: ExpectationMP: measurement process instance """ifisinstance(op,MeasurementValue):returnExpectationMP(obs=op)ifisinstance(op,Sequence):raiseValueError("qml.expval does not support measuring sequences of measurements or observables")ifisinstance(op,qml.Identity)andlen(op.wires)==0:# temporary solution to merge https://github.com/PennyLaneAI/pennylane/pull/5106# allow once we have testing and confidence in qml.expval(I())raiseNotImplementedError("Expectation values of qml.Identity() without wires are currently not allowed.")returnExpectationMP(obs=op)
[docs]classExpectationMP(SampleMeasurement,StateMeasurement):"""Measurement process that computes the expectation value of the supplied observable. Please refer to :func:`pennylane.expval` for detailed documentation. Args: obs (Union[.Operator, .MeasurementValue]): The observable that is to be measured as part of the measurement process. Not all measurement processes require observables (for example ``Probability``); this argument is optional. wires (.Wires): The wires the measurement process applies to. This can only be specified if an observable was not provided. eigvals (array): A flat array representing the eigenvalues of the measurement. This can only be specified if an observable was not provided. id (str): custom label given to a measurement instance, can be useful for some applications where the instance has to be identified """_shortname=Expectation#! Note: deprecated. Change the value to "expval" in v0.42@propertydefnumeric_type(self):returnfloat
[docs]defprocess_samples(self,samples:Sequence[complex],wire_order:Wires,shot_range:Optional[tuple[int,...]]=None,bin_size:Optional[int]=None,):ifnotself.wires:returnqml.math.squeeze(self.eigvals())# estimate the evop=self.mvifself.mvisnotNoneelseself.obswithqml.queuing.QueuingManager.stop_recording():samples=SampleMP(obs=op,eigvals=self._eigvals,wires=self.wiresifself._eigvalsisnotNoneelseNone,).process_samples(samples=samples,wire_order=wire_order,shot_range=shot_range,bin_size=bin_size)# With broadcasting, we want to take the mean over axis 1, which is the -1st/-2nd with/# without bin_size. Without broadcasting, axis 0 is the -1st/-2nd with/without bin_sizeaxis=-1ifbin_sizeisNoneelse-2# TODO: do we need to squeeze here? Maybe remove with new return typesreturnqml.math.squeeze(qml.math.mean(samples,axis=axis))
[docs]defprocess_state(self,state:Sequence[complex],wire_order:Wires):# This also covers statistics for mid-circuit measurements manipulated using# arithmetic operators# we use ``self.wires`` instead of ``self.obs`` because the observable was# already applied to the stateifnotself.wires:returnqml.math.squeeze(self.eigvals())withqml.queuing.QueuingManager.stop_recording():prob=qml.probs(wires=self.wires).process_state(state=state,wire_order=wire_order)# In case of broadcasting, `prob` has two axes and this is a matrix-vector productreturnself._calculate_expectation(prob)
def_calculate_expectation(self,probabilities):""" Calculate the of expectation set of probabilities. Args: probabilities (array): the probabilities of collapsing to eigen states """returnqml.math.dot(probabilities,self.eigvals())